summaryrefslogtreecommitdiffstats
path: root/arch/mips/include
diff options
context:
space:
mode:
authorAntony Pavlov <antonynpavlov@gmail.com>2012-12-12 23:24:46 +0400
committerSascha Hauer <s.hauer@pengutronix.de>2012-12-14 08:34:33 +0100
commitf369f64ed1b29451c82c69c698da60ed8a8eb28f (patch)
tree3dfcdca076f6dbc817b00a65a7b2d695e4b134f6 /arch/mips/include
parent0ccb9aebcd98d99fdc22d938240c65c7466e8146 (diff)
downloadbarebox-f369f64ed1b29451c82c69c698da60ed8a8eb28f.tar.gz
barebox-f369f64ed1b29451c82c69c698da60ed8a8eb28f.tar.xz
MIPS: add pre-bootloader (pbl) image support
This patch is based on ARM pbl support and allows creating a pre-bootloader binary for compressed image. For different MIPS SoCs (or even for different boards based on the same SoC) the operations carried on in start-pbl.S can be very different. The additional constraints can be imposed on the size of the boot code or the special magic labels in the beginning of the boot code; In some cases it could be necessary to show CPU is alive as early as possible (transmit a char via UART or blink a LED). So the demands for pbl start operation can be very different. E.g. malta board store boot code at the NOR flash mapped to the MIPS power-on address (0xbfc00000); it is the most simple case: we need just copy pbl image from direct-mapped flash to RAM and jump there. The XBurst-powered boards store boot code in the beginning of a NAND flash or in the beginning of SD/MMC card. In this case we must use simple and short NAND or SD/MMC access routines to copy pbl image to RAM. To meet so different demands a simple technique is selected: * MIPS pbl entry point located in file arch/mips/boot/start-pbl.S. * MIPS pbl code (see start-pbl.S) assumes that every pbl-enabled board has a arch/mips/boards/<BOARD>/include/board/board_pbl_start.h header file. This file must contain definition of the board_pbl_start macro. This macro is used as start of pbl image; * the most popular asm routines (stack setup, relocation to link address, NS16550 initialization (WIP) and so on) are containt in the arch/mips/include/asm/pbl_macros.h header file. So board pbl macro can use it if necessary. It is possible to create similar headers with macros for each specific SoC; so even if we have many different boards based on the same SoC the board_pbl_start macro for every board can be short and clear. * after board-specific initialization the stack pointer is initialized and pbl C code is started. Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/mips/include')
-rw-r--r--arch/mips/include/asm/pbl_macros.h135
1 files changed, 135 insertions, 0 deletions
diff --git a/arch/mips/include/asm/pbl_macros.h b/arch/mips/include/asm/pbl_macros.h
new file mode 100644
index 0000000000..c32a2296a0
--- /dev/null
+++ b/arch/mips/include/asm/pbl_macros.h
@@ -0,0 +1,135 @@
+/*
+ * Startup Code for MIPS CPU
+ *
+ * Copyright (C) 2011, 2012 Antony Pavlov <antonynpavlov@gmail.com>
+ * ADR macro copyrighted (C) 2009 by Shinya Kuribayashi <skuribay@pobox.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_PBL_MACROS_H
+#define __ASM_PBL_MACROS_H
+
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/asm.h>
+#include <asm-generic/memory_layout.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+
+ /*
+ * ADR macro instruction (inspired by ARM)
+ *
+ * ARM architecture doesn't have PC-relative jump instruction
+ * like MIPS' B/BAL insns. When ARM makes PC-relative jumps,
+ * it uses ADR insn. ADR is used to get a destination address
+ * of 'label' against current PC. With this, ARM can safely
+ * make PC-relative jumps.
+ */
+ .macro ADR rd label temp
+ .set push
+ .set noreorder
+ move \temp, ra # preserve ra beforehand
+ bal _pc
+ nop
+_pc: addiu \rd, ra, \label - _pc # label is assumed to be
+ move ra, \temp # within pc +/- 32KB
+ .set pop
+ .endm
+
+#define LONGSIZE 4
+
+ .macro copy_to_link_location start_addr
+ .set push
+ .set noreorder
+
+ /* copy barebox to link location */
+ ADR a0, \start_addr, t1 /* a0 <- pc-relative
+ position of start_addr */
+
+ la a1, \start_addr /* a1 <- link (RAM) start_addr address */
+
+ beq a0, a1, copy_loop_exit
+ nop
+
+ la t0, \start_addr
+ la t1, __bss_start
+ subu t2, t1, t0 /* t2 <- size of pbl */
+ addu a2, a0, t2 /* a2 <- source end address */
+
+copy_loop:
+ /* copy from source address [a0] */
+ lw t4, LONGSIZE * 0(a0)
+ lw t5, LONGSIZE * 1(a0)
+ lw t6, LONGSIZE * 2(a0)
+ lw t7, LONGSIZE * 3(a0)
+ /* copy to target address [a1] */
+ sw t4, LONGSIZE * 0(a1)
+ sw t5, LONGSIZE * 1(a1)
+ sw t6, LONGSIZE * 2(a1)
+ sw t7, LONGSIZE * 3(a1)
+ addi a0, LONGSIZE * 4
+ subu t3, a0, a2
+ blez t3, copy_loop
+ addi a1, LONGSIZE * 4
+
+copy_loop_exit:
+
+ .set pop
+ .endm
+
+ .macro mips_disable_interrupts
+ .set push
+ .set noreorder
+ mfc0 k0, CP0_STATUS
+ li k1, ~ST0_IE
+ and k0, k1
+ mtc0 k0, CP0_STATUS
+ .set pop
+ .endm
+
+ /*
+ * Dominic Sweetman, See MIPS Run, Morgan Kaufmann, 2nd edition, 2006
+ *
+ * 11.2.2 Stack Argument Structure in o32
+ * ...
+ * At the point where a function is called, sp must be
+ * eight-byte-aligned, matching the alignment of the largest
+ * basic types -- a long long integer or a floating-point double.
+ * The eight-byte alignment is not required by 32-bit MIPS integer
+ * hardware, but it's essential for compatibility with CPUs with
+ * 64-bit registers, and thus part of the rules. Subroutines fit
+ * in with this by always adjusting the stack pointer by a multiple
+ * of eight.
+ * ...
+ * SGI's n32 and n64 standards call for the stack to be maintained
+ * with 16-byte alignment.
+ *
+ */
+
+#if (STACK_BASE + STACK_SIZE) % 16 != 0
+#error stack pointer must be 16-byte-aligned
+#endif
+
+ .macro stack_setup
+ .set push
+ .set noreorder
+
+ /* set stack pointer; reserve four 32-bit argument slots */
+ la sp, STACK_BASE + STACK_SIZE - 16
+
+ .set pop
+ .endm
+
+#endif /* __ASM_PBL_MACROS_H */