GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
|
||||
## Build a couple of necessary functions into a private libgcc
|
||||
## if the user asked for it
|
||||
lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _ashldi3.o _ashrdi3.o _lshrdi3.o
|
||||
|
||||
MINIMAL=
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
ifdef CONFIG_SPL_INIT_MINIMAL
|
||||
MINIMAL=y
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef MINIMAL
|
||||
obj-y += cache.o time.o
|
||||
ifndef CONFIG_TIMER
|
||||
obj-y += ticks.o
|
||||
endif
|
||||
else
|
||||
|
||||
obj-y += ppcstring.o
|
||||
|
||||
obj-y += ppccache.o
|
||||
ifndef CONFIG_TIMER
|
||||
obj-y += ticks.o
|
||||
endif
|
||||
obj-y += reloc.o
|
||||
|
||||
obj-$(CONFIG_BAT_RW) += bat_rw.o
|
||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||
obj-y += cache.o
|
||||
obj-y += extable.o
|
||||
obj-y += interrupts.o
|
||||
obj-$(CONFIG_CMD_KGDB) += kgdb.o
|
||||
obj-y += stack.o
|
||||
obj-y += time.o
|
||||
endif # not minimal
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_$(SPL_TPL)_FRAMEWORK) += spl.o
|
||||
endif
|
||||
@@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* This code was copied from arch/powerpc/kernel/misc_32.S in the Linux
|
||||
* kernel sources (commit 85e2efbb1db9a18d218006706d6e4fbeb0216213, also
|
||||
* known as 2.6.38-rc5). The source file copyrights are as follows:
|
||||
*
|
||||
* (C) Copyright 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
*
|
||||
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
|
||||
* and Paul Mackerras.
|
||||
*/
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
#include <config.h>
|
||||
|
||||
/*
|
||||
* Extended precision shifts.
|
||||
*
|
||||
* Updated to be valid for shift counts from 0 to 63 inclusive.
|
||||
* -- Gabriel
|
||||
*
|
||||
* R3/R4 has 64 bit value
|
||||
* R5 has shift count
|
||||
* result in R3/R4
|
||||
*
|
||||
* ashrdi3: arithmetic right shift (sign propagation)
|
||||
* lshrdi3: logical right shift
|
||||
* ashldi3: left shift
|
||||
*/
|
||||
.globl __ashldi3
|
||||
__ashldi3:
|
||||
subfic r6,r5,32
|
||||
slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
|
||||
addi r7,r5,32 # could be xori, or addi with -32
|
||||
srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
|
||||
slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
|
||||
or r3,r3,r6 # MSW |= t1
|
||||
slw r4,r4,r5 # LSW = LSW << count
|
||||
or r3,r3,r7 # MSW |= t2
|
||||
blr
|
||||
@@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* This code was copied from arch/powerpc/kernel/misc_32.S in the Linux
|
||||
* kernel sources (commit 85e2efbb1db9a18d218006706d6e4fbeb0216213, also
|
||||
* known as 2.6.38-rc5). The source file copyrights are as follows:
|
||||
*
|
||||
* (C) Copyright 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
*
|
||||
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
|
||||
* and Paul Mackerras.
|
||||
*/
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
#include <config.h>
|
||||
|
||||
/*
|
||||
* Extended precision shifts.
|
||||
*
|
||||
* Updated to be valid for shift counts from 0 to 63 inclusive.
|
||||
* -- Gabriel
|
||||
*
|
||||
* R3/R4 has 64 bit value
|
||||
* R5 has shift count
|
||||
* result in R3/R4
|
||||
*
|
||||
* ashrdi3: arithmetic right shift (sign propagation)
|
||||
* lshrdi3: logical right shift
|
||||
* ashldi3: left shift
|
||||
*/
|
||||
.globl __ashrdi3
|
||||
__ashrdi3:
|
||||
subfic r6,r5,32
|
||||
srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
|
||||
addi r7,r5,32 # could be xori, or addi with -32
|
||||
slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
|
||||
rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
|
||||
sraw r7,r3,r7 # t2 = MSW >> (count-32)
|
||||
or r4,r4,r6 # LSW |= t1
|
||||
slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
|
||||
sraw r3,r3,r5 # MSW = MSW >> count
|
||||
or r4,r4,r7 # LSW |= t2
|
||||
blr
|
||||
@@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* This code was copied from arch/powerpc/kernel/misc_32.S in the Linux
|
||||
* kernel sources (commit 85e2efbb1db9a18d218006706d6e4fbeb0216213, also
|
||||
* known as 2.6.38-rc5). The source file copyrights are as follows:
|
||||
*
|
||||
* (C) Copyright 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
*
|
||||
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
|
||||
* and Paul Mackerras.
|
||||
*/
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
#include <config.h>
|
||||
|
||||
/*
|
||||
* Extended precision shifts.
|
||||
*
|
||||
* Updated to be valid for shift counts from 0 to 63 inclusive.
|
||||
* -- Gabriel
|
||||
*
|
||||
* R3/R4 has 64 bit value
|
||||
* R5 has shift count
|
||||
* result in R3/R4
|
||||
*
|
||||
* ashrdi3: arithmetic right shift (sign propagation)
|
||||
* lshrdi3: logical right shift
|
||||
* ashldi3: left shift
|
||||
*/
|
||||
.globl __lshrdi3
|
||||
__lshrdi3:
|
||||
subfic r6,r5,32
|
||||
srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
|
||||
addi r7,r5,32 # could be xori, or addi with -32
|
||||
slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
|
||||
srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
|
||||
or r4,r4,r6 # LSW |= t1
|
||||
srw r3,r3,r5 # MSW = MSW >> count
|
||||
or r4,r4,r7 # LSW |= t2
|
||||
blr
|
||||
@@ -0,0 +1,243 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifdef CONFIG_ADDR_MAP
|
||||
#include <addr_map.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int write_bat (ppc_bat_t bat, unsigned long upper, unsigned long lower)
|
||||
{
|
||||
__maybe_unused int batn = -1;
|
||||
|
||||
sync();
|
||||
|
||||
switch (bat) {
|
||||
case DBAT0:
|
||||
mtspr (DBAT0L, lower);
|
||||
mtspr (DBAT0U, upper);
|
||||
batn = 0;
|
||||
break;
|
||||
case IBAT0:
|
||||
mtspr (IBAT0L, lower);
|
||||
mtspr (IBAT0U, upper);
|
||||
break;
|
||||
case DBAT1:
|
||||
mtspr (DBAT1L, lower);
|
||||
mtspr (DBAT1U, upper);
|
||||
batn = 1;
|
||||
break;
|
||||
case IBAT1:
|
||||
mtspr (IBAT1L, lower);
|
||||
mtspr (IBAT1U, upper);
|
||||
break;
|
||||
case DBAT2:
|
||||
mtspr (DBAT2L, lower);
|
||||
mtspr (DBAT2U, upper);
|
||||
batn = 2;
|
||||
break;
|
||||
case IBAT2:
|
||||
mtspr (IBAT2L, lower);
|
||||
mtspr (IBAT2U, upper);
|
||||
break;
|
||||
case DBAT3:
|
||||
mtspr (DBAT3L, lower);
|
||||
mtspr (DBAT3U, upper);
|
||||
batn = 3;
|
||||
break;
|
||||
case IBAT3:
|
||||
mtspr (IBAT3L, lower);
|
||||
mtspr (IBAT3U, upper);
|
||||
break;
|
||||
#ifdef CONFIG_HIGH_BATS
|
||||
case DBAT4:
|
||||
mtspr (DBAT4L, lower);
|
||||
mtspr (DBAT4U, upper);
|
||||
batn = 4;
|
||||
break;
|
||||
case IBAT4:
|
||||
mtspr (IBAT4L, lower);
|
||||
mtspr (IBAT4U, upper);
|
||||
break;
|
||||
case DBAT5:
|
||||
mtspr (DBAT5L, lower);
|
||||
mtspr (DBAT5U, upper);
|
||||
batn = 5;
|
||||
break;
|
||||
case IBAT5:
|
||||
mtspr (IBAT5L, lower);
|
||||
mtspr (IBAT5U, upper);
|
||||
break;
|
||||
case DBAT6:
|
||||
mtspr (DBAT6L, lower);
|
||||
mtspr (DBAT6U, upper);
|
||||
batn = 6;
|
||||
break;
|
||||
case IBAT6:
|
||||
mtspr (IBAT6L, lower);
|
||||
mtspr (IBAT6U, upper);
|
||||
break;
|
||||
case DBAT7:
|
||||
mtspr (DBAT7L, lower);
|
||||
mtspr (DBAT7U, upper);
|
||||
batn = 7;
|
||||
break;
|
||||
case IBAT7:
|
||||
mtspr (IBAT7L, lower);
|
||||
mtspr (IBAT7U, upper);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ADDR_MAP
|
||||
if ((gd->flags & GD_FLG_RELOC) && (batn >= 0)) {
|
||||
phys_size_t size;
|
||||
if (!BATU_VALID(upper))
|
||||
size = 0;
|
||||
else
|
||||
size = BATU_SIZE(upper);
|
||||
addrmap_set_entry(BATU_VADDR(upper), BATL_PADDR(lower),
|
||||
size, batn);
|
||||
}
|
||||
#endif
|
||||
|
||||
sync();
|
||||
isync();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int read_bat (ppc_bat_t bat, unsigned long *upper, unsigned long *lower)
|
||||
{
|
||||
unsigned long register u;
|
||||
unsigned long register l;
|
||||
|
||||
switch (bat) {
|
||||
case DBAT0:
|
||||
l = mfspr (DBAT0L);
|
||||
u = mfspr (DBAT0U);
|
||||
break;
|
||||
case IBAT0:
|
||||
l = mfspr (IBAT0L);
|
||||
u = mfspr (IBAT0U);
|
||||
break;
|
||||
case DBAT1:
|
||||
l = mfspr (DBAT1L);
|
||||
u = mfspr (DBAT1U);
|
||||
break;
|
||||
case IBAT1:
|
||||
l = mfspr (IBAT1L);
|
||||
u = mfspr (IBAT1U);
|
||||
break;
|
||||
case DBAT2:
|
||||
l = mfspr (DBAT2L);
|
||||
u = mfspr (DBAT2U);
|
||||
break;
|
||||
case IBAT2:
|
||||
l = mfspr (IBAT2L);
|
||||
u = mfspr (IBAT2U);
|
||||
break;
|
||||
case DBAT3:
|
||||
l = mfspr (DBAT3L);
|
||||
u = mfspr (DBAT3U);
|
||||
break;
|
||||
case IBAT3:
|
||||
l = mfspr (IBAT3L);
|
||||
u = mfspr (IBAT3U);
|
||||
break;
|
||||
#ifdef CONFIG_HIGH_BATS
|
||||
case DBAT4:
|
||||
l = mfspr (DBAT4L);
|
||||
u = mfspr (DBAT4U);
|
||||
break;
|
||||
case IBAT4:
|
||||
l = mfspr (IBAT4L);
|
||||
u = mfspr (IBAT4U);
|
||||
break;
|
||||
case DBAT5:
|
||||
l = mfspr (DBAT5L);
|
||||
u = mfspr (DBAT5U);
|
||||
break;
|
||||
case IBAT5:
|
||||
l = mfspr (IBAT5L);
|
||||
u = mfspr (IBAT5U);
|
||||
break;
|
||||
case DBAT6:
|
||||
l = mfspr (DBAT6L);
|
||||
u = mfspr (DBAT6U);
|
||||
break;
|
||||
case IBAT6:
|
||||
l = mfspr (IBAT6L);
|
||||
u = mfspr (IBAT6U);
|
||||
break;
|
||||
case DBAT7:
|
||||
l = mfspr (DBAT7L);
|
||||
u = mfspr (DBAT7U);
|
||||
break;
|
||||
case IBAT7:
|
||||
l = mfspr (IBAT7L);
|
||||
u = mfspr (IBAT7U);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
*upper = u;
|
||||
*lower = l;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void print_bats(void)
|
||||
{
|
||||
printf("BAT registers:\n");
|
||||
|
||||
printf ("\tIBAT0L = 0x%08X ", mfspr (IBAT0L));
|
||||
printf ("\tIBAT0U = 0x%08X\n", mfspr (IBAT0U));
|
||||
printf ("\tDBAT0L = 0x%08X ", mfspr (DBAT0L));
|
||||
printf ("\tDBAT0U = 0x%08X\n", mfspr (DBAT0U));
|
||||
printf ("\tIBAT1L = 0x%08X ", mfspr (IBAT1L));
|
||||
printf ("\tIBAT1U = 0x%08X\n", mfspr (IBAT1U));
|
||||
printf ("\tDBAT1L = 0x%08X ", mfspr (DBAT1L));
|
||||
printf ("\tDBAT1U = 0x%08X\n", mfspr (DBAT1U));
|
||||
printf ("\tIBAT2L = 0x%08X ", mfspr (IBAT2L));
|
||||
printf ("\tIBAT2U = 0x%08X\n", mfspr (IBAT2U));
|
||||
printf ("\tDBAT2L = 0x%08X ", mfspr (DBAT2L));
|
||||
printf ("\tDBAT2U = 0x%08X\n", mfspr (DBAT2U));
|
||||
printf ("\tIBAT3L = 0x%08X ", mfspr (IBAT3L));
|
||||
printf ("\tIBAT3U = 0x%08X\n", mfspr (IBAT3U));
|
||||
printf ("\tDBAT3L = 0x%08X ", mfspr (DBAT3L));
|
||||
printf ("\tDBAT3U = 0x%08X\n", mfspr (DBAT3U));
|
||||
|
||||
#ifdef CONFIG_HIGH_BATS
|
||||
printf ("\tIBAT4L = 0x%08X ", mfspr (IBAT4L));
|
||||
printf ("\tIBAT4U = 0x%08X\n", mfspr (IBAT4U));
|
||||
printf ("\tDBAT4L = 0x%08X ", mfspr (DBAT4L));
|
||||
printf ("\tDBAT4U = 0x%08X\n", mfspr (DBAT4U));
|
||||
printf ("\tIBAT5L = 0x%08X ", mfspr (IBAT5L));
|
||||
printf ("\tIBAT5U = 0x%08X\n", mfspr (IBAT5U));
|
||||
printf ("\tDBAT5L = 0x%08X ", mfspr (DBAT5L));
|
||||
printf ("\tDBAT5U = 0x%08X\n", mfspr (DBAT5U));
|
||||
printf ("\tIBAT6L = 0x%08X ", mfspr (IBAT6L));
|
||||
printf ("\tIBAT6U = 0x%08X\n", mfspr (IBAT6U));
|
||||
printf ("\tDBAT6L = 0x%08X ", mfspr (DBAT6L));
|
||||
printf ("\tDBAT6U = 0x%08X\n", mfspr (DBAT6U));
|
||||
printf ("\tIBAT7L = 0x%08X ", mfspr (IBAT7L));
|
||||
printf ("\tIBAT7U = 0x%08X\n", mfspr (IBAT7U));
|
||||
printf ("\tDBAT7L = 0x%08X ", mfspr (DBAT7L));
|
||||
printf ("\tDBAT7U = 0x%08X\n", mfspr (DBAT7U));
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2008 Semihalf
|
||||
*
|
||||
* (C) Copyright 2000-2006
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*/
|
||||
|
||||
|
||||
#include <common.h>
|
||||
#include <cpu_func.h>
|
||||
#include <env.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
#include <malloc.h>
|
||||
#include <u-boot/zlib.h>
|
||||
#include <bzlib.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/mp.h>
|
||||
#include <bootm.h>
|
||||
#include <vxworks.h>
|
||||
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
#include <linux/libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_INIT_RAM_LOCK
|
||||
#include <asm/cache.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static ulong get_sp (void);
|
||||
extern void ft_fixup_num_cores(void *blob);
|
||||
static void set_clocks_in_mhz (bd_t *kbd);
|
||||
|
||||
#ifndef CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE
|
||||
#define CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE (768*1024*1024)
|
||||
#endif
|
||||
|
||||
static void boot_jump_linux(bootm_headers_t *images)
|
||||
{
|
||||
void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6,
|
||||
ulong r7, ulong r8, ulong r9);
|
||||
#ifdef CONFIG_OF_LIBFDT
|
||||
char *of_flat_tree = images->ft_addr;
|
||||
#endif
|
||||
|
||||
kernel = (void (*)(bd_t *, ulong, ulong, ulong,
|
||||
ulong, ulong, ulong))images->ep;
|
||||
debug ("## Transferring control to Linux (at address %08lx) ...\n",
|
||||
(ulong)kernel);
|
||||
|
||||
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
|
||||
|
||||
#ifdef CONFIG_BOOTSTAGE_FDT
|
||||
bootstage_fdt_add_report();
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTSTAGE_REPORT
|
||||
bootstage_report();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500)
|
||||
unlock_ram_in_cache();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
if (of_flat_tree) { /* device tree; boot new style */
|
||||
/*
|
||||
* Linux Kernel Parameters (passing device tree):
|
||||
* r3: pointer to the fdt
|
||||
* r4: 0
|
||||
* r5: 0
|
||||
* r6: epapr magic
|
||||
* r7: size of IMA in bytes
|
||||
* r8: 0
|
||||
* r9: 0
|
||||
*/
|
||||
debug (" Booting using OF flat tree...\n");
|
||||
WATCHDOG_RESET ();
|
||||
(*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC,
|
||||
env_get_bootm_mapsize(), 0, 0);
|
||||
/* does not return */
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Linux Kernel Parameters (passing board info data):
|
||||
* r3: ptr to board info data
|
||||
* r4: initrd_start or 0 if no initrd
|
||||
* r5: initrd_end - unused if r4 is 0
|
||||
* r6: Start of command line string
|
||||
* r7: End of command line string
|
||||
* r8: 0
|
||||
* r9: 0
|
||||
*/
|
||||
ulong cmd_start = images->cmdline_start;
|
||||
ulong cmd_end = images->cmdline_end;
|
||||
ulong initrd_start = images->initrd_start;
|
||||
ulong initrd_end = images->initrd_end;
|
||||
bd_t *kbd = images->kbd;
|
||||
|
||||
debug (" Booting using board info...\n");
|
||||
WATCHDOG_RESET ();
|
||||
(*kernel) (kbd, initrd_start, initrd_end,
|
||||
cmd_start, cmd_end, 0, 0);
|
||||
/* does not return */
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
void arch_lmb_reserve(struct lmb *lmb)
|
||||
{
|
||||
phys_size_t bootm_size;
|
||||
ulong size, sp, bootmap_base;
|
||||
|
||||
bootmap_base = env_get_bootm_low();
|
||||
bootm_size = env_get_bootm_size();
|
||||
|
||||
#ifdef DEBUG
|
||||
if (((u64)bootmap_base + bootm_size) >
|
||||
(CONFIG_SYS_SDRAM_BASE + (u64)gd->ram_size))
|
||||
puts("WARNING: bootm_low + bootm_size exceed total memory\n");
|
||||
if ((bootmap_base + bootm_size) > get_effective_memsize())
|
||||
puts("WARNING: bootm_low + bootm_size exceed eff. memory\n");
|
||||
#endif
|
||||
|
||||
size = min(bootm_size, get_effective_memsize());
|
||||
size = min(size, (ulong)CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE);
|
||||
|
||||
if (size < bootm_size) {
|
||||
ulong base = bootmap_base + size;
|
||||
printf("WARNING: adjusting available memory to %lx\n", size);
|
||||
lmb_reserve(lmb, base, bootm_size - size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Booting a (Linux) kernel image
|
||||
*
|
||||
* Allocate space for command line and board info - the
|
||||
* address should be as high as possible within the reach of
|
||||
* the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
|
||||
* memory, which means far enough below the current stack
|
||||
* pointer.
|
||||
*/
|
||||
sp = get_sp();
|
||||
debug ("## Current stack ends at 0x%08lx\n", sp);
|
||||
|
||||
/* adjust sp by 4K to be safe */
|
||||
sp -= 4096;
|
||||
lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - sp));
|
||||
|
||||
#ifdef CONFIG_MP
|
||||
cpu_mp_lmb_reserve(lmb);
|
||||
#endif
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
static void boot_prep_linux(bootm_headers_t *images)
|
||||
{
|
||||
#ifdef CONFIG_MP
|
||||
/*
|
||||
* if we are MP make sure to flush the device tree so any changes are
|
||||
* made visibile to all other cores. In AMP boot scenarios the cores
|
||||
* might not be HW cache coherent with each other.
|
||||
*/
|
||||
flush_cache((unsigned long)images->ft_addr, images->ft_len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int boot_cmdline_linux(bootm_headers_t *images)
|
||||
{
|
||||
ulong of_size = images->ft_len;
|
||||
struct lmb *lmb = &images->lmb;
|
||||
ulong *cmd_start = &images->cmdline_start;
|
||||
ulong *cmd_end = &images->cmdline_end;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (!of_size) {
|
||||
/* allocate space and init command line */
|
||||
ret = boot_get_cmdline (lmb, cmd_start, cmd_end);
|
||||
if (ret) {
|
||||
puts("ERROR with allocation of cmdline\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int boot_bd_t_linux(bootm_headers_t *images)
|
||||
{
|
||||
ulong of_size = images->ft_len;
|
||||
struct lmb *lmb = &images->lmb;
|
||||
bd_t **kbd = &images->kbd;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (!of_size) {
|
||||
/* allocate space for kernel copy of board info */
|
||||
ret = boot_get_kbd (lmb, kbd);
|
||||
if (ret) {
|
||||
puts("ERROR with allocation of kernel bd\n");
|
||||
return ret;
|
||||
}
|
||||
set_clocks_in_mhz(*kbd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int boot_body_linux(bootm_headers_t *images)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* allocate space for kernel copy of board info */
|
||||
ret = boot_bd_t_linux(images);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = image_setup_linux(images);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
noinline
|
||||
int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flag & BOOTM_STATE_OS_CMDLINE) {
|
||||
boot_cmdline_linux(images);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flag & BOOTM_STATE_OS_BD_T) {
|
||||
boot_bd_t_linux(images);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flag & BOOTM_STATE_OS_PREP) {
|
||||
boot_prep_linux(images);
|
||||
return 0;
|
||||
}
|
||||
|
||||
boot_prep_linux(images);
|
||||
ret = boot_body_linux(images);
|
||||
if (ret)
|
||||
return ret;
|
||||
boot_jump_linux(images);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong get_sp (void)
|
||||
{
|
||||
ulong sp;
|
||||
|
||||
asm( "mr %0,1": "=r"(sp) : );
|
||||
return sp;
|
||||
}
|
||||
|
||||
static void set_clocks_in_mhz (bd_t *kbd)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = env_get("clocks_in_mhz");
|
||||
if (s) {
|
||||
/* convert all clock information to MHz */
|
||||
kbd->bi_intfreq /= 1000000L;
|
||||
kbd->bi_busfreq /= 1000000L;
|
||||
#if defined(CONFIG_CPM2)
|
||||
kbd->bi_cpmfreq /= 1000000L;
|
||||
kbd->bi_brgfreq /= 1000000L;
|
||||
kbd->bi_sccfreq /= 1000000L;
|
||||
kbd->bi_vco /= 1000000L;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BOOTM_VXWORKS)
|
||||
void boot_prep_vxworks(bootm_headers_t *images)
|
||||
{
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
int off;
|
||||
u64 base, size;
|
||||
|
||||
if (!images->ft_addr)
|
||||
return;
|
||||
|
||||
base = (u64)gd->bd->bi_memstart;
|
||||
size = (u64)gd->bd->bi_memsize;
|
||||
|
||||
off = fdt_path_offset(images->ft_addr, "/memory");
|
||||
if (off < 0)
|
||||
fdt_fixup_memory(images->ft_addr, base, size);
|
||||
|
||||
#if defined(CONFIG_MP)
|
||||
#if defined(CONFIG_MPC85xx)
|
||||
ft_fixup_cpu(images->ft_addr, base + size);
|
||||
ft_fixup_num_cores(images->ft_addr);
|
||||
#elif defined(CONFIG_MPC86xx)
|
||||
off = fdt_add_mem_rsv(images->ft_addr,
|
||||
determine_mp_bootpg(NULL), (u64)4096);
|
||||
if (off < 0)
|
||||
printf("## WARNING %s: %s\n", __func__, fdt_strerror(off));
|
||||
ft_fixup_num_cores(images->ft_addr);
|
||||
#endif
|
||||
flush_cache((unsigned long)images->ft_addr, images->ft_len);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void boot_jump_vxworks(bootm_headers_t *images)
|
||||
{
|
||||
/* PowerPC VxWorks boot interface conforms to the ePAPR standard
|
||||
* general purpuse registers:
|
||||
*
|
||||
* r3: Effective address of the device tree image
|
||||
* r4: 0
|
||||
* r5: 0
|
||||
* r6: ePAPR magic value
|
||||
* r7: shall be the size of the boot IMA in bytes
|
||||
* r8: 0
|
||||
* r9: 0
|
||||
* TCR: WRC = 0, no watchdog timer reset will occur
|
||||
*/
|
||||
WATCHDOG_RESET();
|
||||
|
||||
((void (*)(void *, ulong, ulong, ulong,
|
||||
ulong, ulong, ulong))images->ep)(images->ft_addr,
|
||||
0, 0, EPAPR_MAGIC, env_get_bootm_mapsize(), 0, 0);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <cpu_func.h>
|
||||
#include <asm/cache.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
void flush_cache(ulong start_addr, ulong size)
|
||||
{
|
||||
#ifndef CONFIG_5xx
|
||||
ulong addr, start, end;
|
||||
|
||||
start = start_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
|
||||
end = start_addr + size - 1;
|
||||
|
||||
for (addr = start; (addr <= end) && (addr >= start);
|
||||
addr += CONFIG_SYS_CACHELINE_SIZE) {
|
||||
asm volatile("dcbst 0,%0" : : "r" (addr) : "memory");
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
/* wait for all dcbst to complete on bus */
|
||||
asm volatile("sync" : : : "memory");
|
||||
|
||||
for (addr = start; (addr <= end) && (addr >= start);
|
||||
addr += CONFIG_SYS_CACHELINE_SIZE) {
|
||||
asm volatile("icbi 0,%0" : : "r" (addr) : "memory");
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
asm volatile("sync" : : : "memory");
|
||||
/* flush prefetch queue */
|
||||
asm volatile("isync" : : : "memory");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
|
||||
*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*/
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
* The exception table consists of pairs of addresses: the first is the
|
||||
* address of an instruction that is allowed to fault, and the second is
|
||||
* the address at which the program should continue. No registers are
|
||||
* modified, so it is entirely up to the continuation code to figure out
|
||||
* what to do.
|
||||
*
|
||||
* All the routines below use bits of fixup code that are out of line
|
||||
* with the main instruction path. This means when everything is well,
|
||||
* we don't even have to jump over them. Further, they do not intrude
|
||||
* on our cache or tlb entries.
|
||||
*/
|
||||
|
||||
struct exception_table_entry
|
||||
{
|
||||
unsigned long insn, fixup;
|
||||
};
|
||||
|
||||
extern const struct exception_table_entry __start___ex_table[];
|
||||
extern const struct exception_table_entry __stop___ex_table[];
|
||||
|
||||
static inline unsigned long
|
||||
search_one_table(const struct exception_table_entry *first,
|
||||
const struct exception_table_entry *last,
|
||||
unsigned long value)
|
||||
{
|
||||
long diff;
|
||||
while (first <= last) {
|
||||
diff = first->insn - value;
|
||||
if (diff == 0)
|
||||
return first->fixup;
|
||||
first++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
search_exception_table(unsigned long addr)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
/* There is only the kernel to search. */
|
||||
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
|
||||
/* if the serial port does not hang in exception, printf can be used */
|
||||
#if !defined(CONFIG_SYS_SERIAL_HANG_IN_EXCEPTION)
|
||||
debug("Bus Fault @ 0x%08lx, fixup 0x%08lx\n", addr, ret);
|
||||
#endif
|
||||
if (ret) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2003
|
||||
* Gleb Natapov <gnatapov@mrv.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <irq_func.h>
|
||||
#include <asm/processor.h>
|
||||
#include <watchdog.h>
|
||||
#ifdef CONFIG_LED_STATUS
|
||||
#include <status_led.h>
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_MPC83XX_TIMER
|
||||
#ifndef CONFIG_SYS_WATCHDOG_FREQ
|
||||
#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
|
||||
#endif
|
||||
|
||||
static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
|
||||
|
||||
static __inline__ unsigned long get_dec (void)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
asm volatile ("mfdec %0":"=r" (val):);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static __inline__ void set_dec (unsigned long val)
|
||||
{
|
||||
if (val)
|
||||
asm volatile ("mtdec %0"::"r" (val));
|
||||
}
|
||||
#endif /* !CONFIG_MPC83XX_TIMER */
|
||||
|
||||
void enable_interrupts(void)
|
||||
{
|
||||
set_msr (get_msr () | MSR_EE);
|
||||
}
|
||||
|
||||
/* returns flag if MSR_EE was set before */
|
||||
int disable_interrupts(void)
|
||||
{
|
||||
ulong msr = get_msr ();
|
||||
|
||||
set_msr (msr & ~MSR_EE);
|
||||
return ((msr & MSR_EE) != 0);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MPC83XX_TIMER
|
||||
int interrupt_init(void)
|
||||
{
|
||||
/* call cpu specific function from $(CPU)/interrupts.c */
|
||||
interrupt_init_cpu (&decrementer_count);
|
||||
|
||||
set_dec (decrementer_count);
|
||||
|
||||
set_msr (get_msr () | MSR_EE);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static volatile ulong timestamp = 0;
|
||||
|
||||
void timer_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
/* call cpu specific function from $(CPU)/interrupts.c */
|
||||
timer_interrupt_cpu (regs);
|
||||
|
||||
/* Restore Decrementer Count */
|
||||
set_dec (decrementer_count);
|
||||
|
||||
timestamp++;
|
||||
|
||||
#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
|
||||
if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
|
||||
WATCHDOG_RESET ();
|
||||
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
|
||||
|
||||
#ifdef CONFIG_LED_STATUS
|
||||
status_led_tick(timestamp);
|
||||
#endif /* CONFIG_LED_STATUS */
|
||||
}
|
||||
|
||||
ulong get_timer (ulong base)
|
||||
{
|
||||
return (timestamp - base);
|
||||
}
|
||||
#endif /* !CONFIG_MPC83XX_TIMER */
|
||||
@@ -0,0 +1,260 @@
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <kgdb.h>
|
||||
#include <asm/signal.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define PC_REGNUM 64
|
||||
#define SP_REGNUM 1
|
||||
|
||||
void breakinst(void);
|
||||
|
||||
int
|
||||
kgdb_setjmp(long *buf)
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
asm volatile("mflr %0; stw %0,0(%1);"
|
||||
"stw %%r1,4(%1); stw %%r2,8(%1);"
|
||||
"mfcr %0; stw %0,12(%1);"
|
||||
"stmw %%r13,16(%1)"
|
||||
: "=&r"(temp) : "r" (buf));
|
||||
/* XXX should save fp regs as well */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
kgdb_longjmp(long *buf, int val)
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
if (val == 0)
|
||||
val = 1;
|
||||
|
||||
asm volatile("lmw %%r13,16(%1);"
|
||||
"lwz %0,12(%1); mtcrf 0x38,%0;"
|
||||
"lwz %0,0(%1); lwz %%r1,4(%1); lwz %%r2,8(%1);"
|
||||
"mtlr %0; mr %%r3,%2"
|
||||
: "=&r"(temp) : "r" (buf), "r" (val));
|
||||
}
|
||||
|
||||
/* Convert the SPARC hardware trap type code to a unix signal number. */
|
||||
/*
|
||||
* This table contains the mapping between PowerPC hardware trap types, and
|
||||
* signals, which are primarily what GDB understands.
|
||||
*/
|
||||
static struct hard_trap_info
|
||||
{
|
||||
unsigned int tt; /* Trap type code for powerpc */
|
||||
unsigned char signo; /* Signal that we map this trap into */
|
||||
} hard_trap_info[] = {
|
||||
{ 0x200, SIGSEGV }, /* machine check */
|
||||
{ 0x300, SIGSEGV }, /* address error (store) */
|
||||
{ 0x400, SIGBUS }, /* instruction bus error */
|
||||
{ 0x500, SIGINT }, /* interrupt */
|
||||
{ 0x600, SIGBUS }, /* alignment */
|
||||
{ 0x700, SIGTRAP }, /* breakpoint trap */
|
||||
{ 0x800, SIGFPE }, /* fpu unavail */
|
||||
{ 0x900, SIGALRM }, /* decrementer */
|
||||
{ 0xa00, SIGILL }, /* reserved */
|
||||
{ 0xb00, SIGILL }, /* reserved */
|
||||
{ 0xc00, SIGCHLD }, /* syscall */
|
||||
{ 0xd00, SIGTRAP }, /* single-step/watch */
|
||||
{ 0xe00, SIGFPE }, /* fp assist */
|
||||
{ 0, 0} /* Must be last */
|
||||
};
|
||||
|
||||
static int
|
||||
computeSignal(unsigned int tt)
|
||||
{
|
||||
struct hard_trap_info *ht;
|
||||
|
||||
for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
|
||||
if (ht->tt == tt)
|
||||
return ht->signo;
|
||||
|
||||
return SIGHUP; /* default for things we don't know about */
|
||||
}
|
||||
|
||||
void
|
||||
kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
|
||||
{
|
||||
unsigned long msr;
|
||||
|
||||
kdp->private[0] = msr = get_msr();
|
||||
set_msr(msr & ~MSR_EE); /* disable interrupts */
|
||||
|
||||
if (regs->nip == (unsigned long)breakinst) {
|
||||
/* Skip over breakpoint trap insn */
|
||||
regs->nip += 4;
|
||||
}
|
||||
regs->msr &= ~MSR_SE;
|
||||
|
||||
/* reply to host that an exception has occurred */
|
||||
kdp->sigval = computeSignal(regs->trap);
|
||||
|
||||
kdp->nregs = 2;
|
||||
|
||||
kdp->regs[0].num = PC_REGNUM;
|
||||
kdp->regs[0].val = regs->nip;
|
||||
|
||||
kdp->regs[1].num = SP_REGNUM;
|
||||
kdp->regs[1].val = regs->gpr[SP_REGNUM];
|
||||
}
|
||||
|
||||
void
|
||||
kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
|
||||
{
|
||||
unsigned long msr = kdp->private[0];
|
||||
|
||||
if (kdp->extype & KGDBEXIT_WITHADDR)
|
||||
regs->nip = kdp->exaddr;
|
||||
|
||||
switch (kdp->extype & KGDBEXIT_TYPEMASK) {
|
||||
|
||||
case KGDBEXIT_KILL:
|
||||
case KGDBEXIT_CONTINUE:
|
||||
set_msr(msr);
|
||||
break;
|
||||
|
||||
case KGDBEXIT_SINGLE:
|
||||
regs->msr |= MSR_SE;
|
||||
#if 0
|
||||
set_msr(msr | MSR_SE);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
kgdb_trap(struct pt_regs *regs)
|
||||
{
|
||||
return (regs->trap);
|
||||
}
|
||||
|
||||
/* return the value of the CPU registers.
|
||||
* some of them are non-PowerPC names :(
|
||||
* they are stored in gdb like:
|
||||
* struct {
|
||||
* u32 gpr[32];
|
||||
* f64 fpr[32];
|
||||
* u32 pc, ps, cnd, lr; (ps=msr)
|
||||
* u32 cnt, xer, mq;
|
||||
* }
|
||||
*/
|
||||
|
||||
#define SPACE_REQUIRED ((32*4)+(32*8)+(6*4))
|
||||
|
||||
int
|
||||
kgdb_getregs(struct pt_regs *regs, char *buf, int max)
|
||||
{
|
||||
int i;
|
||||
unsigned long *ptr = (unsigned long *)buf;
|
||||
|
||||
if (max < SPACE_REQUIRED)
|
||||
kgdb_error(KGDBERR_NOSPACE);
|
||||
|
||||
if ((unsigned long)ptr & 3)
|
||||
kgdb_error(KGDBERR_ALIGNFAULT);
|
||||
|
||||
/* General Purpose Regs */
|
||||
for (i = 0; i < 32; i++)
|
||||
*ptr++ = regs->gpr[i];
|
||||
|
||||
/* Floating Point Regs */
|
||||
for (i = 0; i < 32; i++) {
|
||||
*ptr++ = 0;
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
/* pc, msr, cr, lr, ctr, xer, (mq is unused) */
|
||||
*ptr++ = regs->nip;
|
||||
*ptr++ = regs->msr;
|
||||
*ptr++ = regs->ccr;
|
||||
*ptr++ = regs->link;
|
||||
*ptr++ = regs->ctr;
|
||||
*ptr++ = regs->xer;
|
||||
|
||||
return (SPACE_REQUIRED);
|
||||
}
|
||||
|
||||
/* set the value of the CPU registers */
|
||||
void
|
||||
kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
|
||||
{
|
||||
unsigned long *ptr = (unsigned long *)buf;
|
||||
|
||||
if (regno < 0 || regno >= 70)
|
||||
kgdb_error(KGDBERR_BADPARAMS);
|
||||
else if (regno >= 32 && regno < 64) {
|
||||
if (length < 8)
|
||||
kgdb_error(KGDBERR_NOSPACE);
|
||||
}
|
||||
else {
|
||||
if (length < 4)
|
||||
kgdb_error(KGDBERR_NOSPACE);
|
||||
}
|
||||
|
||||
if ((unsigned long)ptr & 3)
|
||||
kgdb_error(KGDBERR_ALIGNFAULT);
|
||||
|
||||
if (regno >= 0 && regno < 32)
|
||||
regs->gpr[regno] = *ptr;
|
||||
else switch (regno) {
|
||||
case 64: regs->nip = *ptr; break;
|
||||
case 65: regs->msr = *ptr; break;
|
||||
case 66: regs->ccr = *ptr; break;
|
||||
case 67: regs->link = *ptr; break;
|
||||
case 68: regs->ctr = *ptr; break;
|
||||
case 69: regs->ctr = *ptr; break;
|
||||
|
||||
default:
|
||||
kgdb_error(KGDBERR_BADPARAMS);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
kgdb_putregs(struct pt_regs *regs, char *buf, int length)
|
||||
{
|
||||
int i;
|
||||
unsigned long *ptr = (unsigned long *)buf;
|
||||
|
||||
if (length < SPACE_REQUIRED)
|
||||
kgdb_error(KGDBERR_NOSPACE);
|
||||
|
||||
if ((unsigned long)ptr & 3)
|
||||
kgdb_error(KGDBERR_ALIGNFAULT);
|
||||
|
||||
/*
|
||||
* If the stack pointer has moved, you should pray.
|
||||
* (cause only god can help you).
|
||||
*/
|
||||
|
||||
/* General Purpose Regs */
|
||||
for (i = 0; i < 32; i++)
|
||||
regs->gpr[i] = *ptr++;
|
||||
|
||||
/* Floating Point Regs */
|
||||
ptr += 32*2;
|
||||
|
||||
/* pc, msr, cr, lr, ctr, xer, (mq is unused) */
|
||||
regs->nip = *ptr++;
|
||||
regs->msr = *ptr++;
|
||||
regs->ccr = *ptr++;
|
||||
regs->link = *ptr++;
|
||||
regs->ctr = *ptr++;
|
||||
regs->xer = *ptr++;
|
||||
}
|
||||
|
||||
/* This function will generate a breakpoint exception. It is used at the
|
||||
beginning of a program to sync up with a debugger and can be used
|
||||
otherwise as a quick means to stop program execution and "break" into
|
||||
the debugger. */
|
||||
|
||||
void
|
||||
kgdb_breakpoint(int argc, char * const argv[])
|
||||
{
|
||||
asm(" .globl breakinst\n\
|
||||
breakinst: .long 0x7d821008\n\
|
||||
");
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
|
||||
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
|
||||
* Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
|
||||
* Copyright Freescale Semiconductor, Inc. 2004, 2006.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
|
||||
#include <asm/cache.h>
|
||||
|
||||
/*------------------------------------------------------------------------------- */
|
||||
/* Function: ppcDcbf */
|
||||
/* Description: Data Cache block flush */
|
||||
/* Input: r3 = effective address */
|
||||
/* Output: none. */
|
||||
/*------------------------------------------------------------------------------- */
|
||||
.globl ppcDcbf
|
||||
ppcDcbf:
|
||||
dcbf r0,r3
|
||||
blr
|
||||
|
||||
/*------------------------------------------------------------------------------- */
|
||||
/* Function: ppcDcbi */
|
||||
/* Description: Data Cache block Invalidate */
|
||||
/* Input: r3 = effective address */
|
||||
/* Output: none. */
|
||||
/*------------------------------------------------------------------------------- */
|
||||
.globl ppcDcbi
|
||||
ppcDcbi:
|
||||
dcbi r0,r3
|
||||
blr
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Function: ppcDcbz
|
||||
* Description: Data Cache block zero.
|
||||
* Input: r3 = effective address
|
||||
* Output: none.
|
||||
*-------------------------------------------------------------------------- */
|
||||
|
||||
.globl ppcDcbz
|
||||
ppcDcbz:
|
||||
dcbz r0,r3
|
||||
blr
|
||||
|
||||
/*------------------------------------------------------------------------------- */
|
||||
/* Function: ppcSync */
|
||||
/* Description: Processor Synchronize */
|
||||
/* Input: none. */
|
||||
/* Output: none. */
|
||||
/*------------------------------------------------------------------------------- */
|
||||
.globl ppcSync
|
||||
ppcSync:
|
||||
sync
|
||||
blr
|
||||
|
||||
/*
|
||||
* Write any modified data cache blocks out to memory and invalidate them.
|
||||
* Does not invalidate the corresponding instruction cache blocks.
|
||||
*
|
||||
* flush_dcache_range(unsigned long start, unsigned long stop)
|
||||
*/
|
||||
_GLOBAL(flush_dcache_range)
|
||||
#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
|
||||
li r5,L1_CACHE_BYTES-1
|
||||
andc r3,r3,r5
|
||||
subf r4,r3,r4
|
||||
add r4,r4,r5
|
||||
srwi. r4,r4,L1_CACHE_SHIFT
|
||||
beqlr
|
||||
mtctr r4
|
||||
|
||||
1: dcbf 0,r3
|
||||
addi r3,r3,L1_CACHE_BYTES
|
||||
bdnz 1b
|
||||
sync /* wait for dcbst's to get to ram */
|
||||
#endif
|
||||
blr
|
||||
|
||||
/*
|
||||
* Like above, but invalidate the D-cache. This is used by the 8xx
|
||||
* to invalidate the cache so the PPC core doesn't get stale data
|
||||
* from the CPM (no cache snooping here :-).
|
||||
*
|
||||
* invalidate_dcache_range(unsigned long start, unsigned long stop)
|
||||
*/
|
||||
_GLOBAL(invalidate_dcache_range)
|
||||
#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
|
||||
li r5,L1_CACHE_BYTES-1
|
||||
andc r3,r3,r5
|
||||
subf r4,r3,r4
|
||||
add r4,r4,r5
|
||||
srwi. r4,r4,L1_CACHE_SHIFT
|
||||
beqlr
|
||||
mtctr r4
|
||||
|
||||
sync
|
||||
1: dcbi 0,r3
|
||||
addi r3,r3,L1_CACHE_BYTES
|
||||
bdnz 1b
|
||||
sync /* wait for dcbi's to get to ram */
|
||||
#endif
|
||||
blr
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* String handling functions for PowerPC.
|
||||
*
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
*/
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <linux/errno.h>
|
||||
|
||||
.globl strcpy
|
||||
strcpy:
|
||||
addi r5,r3,-1
|
||||
addi r4,r4,-1
|
||||
1: lbzu r0,1(r4)
|
||||
cmpwi 0,r0,0
|
||||
stbu r0,1(r5)
|
||||
bne 1b
|
||||
blr
|
||||
|
||||
.globl strncpy
|
||||
strncpy:
|
||||
cmpwi 0,r5,0
|
||||
beqlr
|
||||
mtctr r5
|
||||
addi r6,r3,-1
|
||||
addi r4,r4,-1
|
||||
1: lbzu r0,1(r4)
|
||||
cmpwi 0,r0,0
|
||||
stbu r0,1(r6)
|
||||
bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
|
||||
blr
|
||||
|
||||
.globl strcat
|
||||
strcat:
|
||||
addi r5,r3,-1
|
||||
addi r4,r4,-1
|
||||
1: lbzu r0,1(r5)
|
||||
cmpwi 0,r0,0
|
||||
bne 1b
|
||||
addi r5,r5,-1
|
||||
1: lbzu r0,1(r4)
|
||||
cmpwi 0,r0,0
|
||||
stbu r0,1(r5)
|
||||
bne 1b
|
||||
blr
|
||||
|
||||
.globl strcmp
|
||||
strcmp:
|
||||
addi r5,r3,-1
|
||||
addi r4,r4,-1
|
||||
1: lbzu r3,1(r5)
|
||||
cmpwi 1,r3,0
|
||||
lbzu r0,1(r4)
|
||||
subf. r3,r0,r3
|
||||
beqlr 1
|
||||
beq 1b
|
||||
blr
|
||||
|
||||
.globl strlen
|
||||
strlen:
|
||||
addi r4,r3,-1
|
||||
1: lbzu r0,1(r4)
|
||||
cmpwi 0,r0,0
|
||||
bne 1b
|
||||
subf r3,r3,r4
|
||||
blr
|
||||
|
||||
.globl memset
|
||||
memset:
|
||||
rlwimi r4,r4,8,16,23
|
||||
rlwimi r4,r4,16,0,15
|
||||
addi r6,r3,-4
|
||||
cmplwi 0,r5,4
|
||||
blt 7f
|
||||
stwu r4,4(r6)
|
||||
beqlr
|
||||
andi. r0,r6,3
|
||||
add r5,r0,r5
|
||||
subf r6,r0,r6
|
||||
rlwinm r0,r5,32-2,2,31
|
||||
mtctr r0
|
||||
bdz 6f
|
||||
1: stwu r4,4(r6)
|
||||
bdnz 1b
|
||||
6: andi. r5,r5,3
|
||||
7: cmpwi 0,r5,0
|
||||
beqlr
|
||||
mtctr r5
|
||||
addi r6,r6,3
|
||||
8: stbu r4,1(r6)
|
||||
bdnz 8b
|
||||
blr
|
||||
|
||||
.globl memmove
|
||||
memmove:
|
||||
cmplw 0,r3,r4
|
||||
bgt backwards_memcpy
|
||||
/* fall through */
|
||||
|
||||
.globl memcpy
|
||||
memcpy:
|
||||
rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
|
||||
addi r6,r3,-4
|
||||
addi r4,r4,-4
|
||||
beq 2f /* if less than 8 bytes to do */
|
||||
andi. r0,r6,3 /* get dest word aligned */
|
||||
mtctr r7
|
||||
bne 5f
|
||||
1: lwz r7,4(r4)
|
||||
lwzu r8,8(r4)
|
||||
stw r7,4(r6)
|
||||
stwu r8,8(r6)
|
||||
bdnz 1b
|
||||
andi. r5,r5,7
|
||||
2: cmplwi 0,r5,4
|
||||
blt 3f
|
||||
lwzu r0,4(r4)
|
||||
addi r5,r5,-4
|
||||
stwu r0,4(r6)
|
||||
3: cmpwi 0,r5,0
|
||||
beqlr
|
||||
mtctr r5
|
||||
addi r4,r4,3
|
||||
addi r6,r6,3
|
||||
4: lbzu r0,1(r4)
|
||||
stbu r0,1(r6)
|
||||
bdnz 4b
|
||||
blr
|
||||
5: subfic r0,r0,4
|
||||
mtctr r0
|
||||
6: lbz r7,4(r4)
|
||||
addi r4,r4,1
|
||||
stb r7,4(r6)
|
||||
addi r6,r6,1
|
||||
bdnz 6b
|
||||
subf r5,r0,r5
|
||||
rlwinm. r7,r5,32-3,3,31
|
||||
beq 2b
|
||||
mtctr r7
|
||||
b 1b
|
||||
|
||||
.globl backwards_memcpy
|
||||
backwards_memcpy:
|
||||
rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
|
||||
add r6,r3,r5
|
||||
add r4,r4,r5
|
||||
beq 2f
|
||||
andi. r0,r6,3
|
||||
mtctr r7
|
||||
bne 5f
|
||||
1: lwz r7,-4(r4)
|
||||
lwzu r8,-8(r4)
|
||||
stw r7,-4(r6)
|
||||
stwu r8,-8(r6)
|
||||
bdnz 1b
|
||||
andi. r5,r5,7
|
||||
2: cmplwi 0,r5,4
|
||||
blt 3f
|
||||
lwzu r0,-4(r4)
|
||||
subi r5,r5,4
|
||||
stwu r0,-4(r6)
|
||||
3: cmpwi 0,r5,0
|
||||
beqlr
|
||||
mtctr r5
|
||||
4: lbzu r0,-1(r4)
|
||||
stbu r0,-1(r6)
|
||||
bdnz 4b
|
||||
blr
|
||||
5: mtctr r0
|
||||
6: lbzu r7,-1(r4)
|
||||
stbu r7,-1(r6)
|
||||
bdnz 6b
|
||||
subf r5,r0,r5
|
||||
rlwinm. r7,r5,32-3,3,31
|
||||
beq 2b
|
||||
mtctr r7
|
||||
b 1b
|
||||
|
||||
.globl memcmp
|
||||
memcmp:
|
||||
cmpwi 0,r5,0
|
||||
ble- 2f
|
||||
mtctr r5
|
||||
addi r6,r3,-1
|
||||
addi r4,r4,-1
|
||||
1: lbzu r3,1(r6)
|
||||
lbzu r0,1(r4)
|
||||
subf. r3,r0,r3
|
||||
bdnzt 2,1b
|
||||
blr
|
||||
2: li r3,0
|
||||
blr
|
||||
|
||||
.global memchr
|
||||
memchr:
|
||||
cmpwi 0,r5,0
|
||||
ble- 2f
|
||||
mtctr r5
|
||||
addi r3,r3,-1
|
||||
1: lbzu r0,1(r3)
|
||||
cmpw 0,r0,r4
|
||||
bdnzf 2,1b
|
||||
beqlr
|
||||
2: li r3,0
|
||||
blr
|
||||
@@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2009 Wolfgang Denk <wd@denx.de>
|
||||
*/
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
.file "reloc.S"
|
||||
|
||||
.text
|
||||
#ifndef CONFIG_NAND_SPL
|
||||
/*
|
||||
* Function: relocate entries for one exception vector
|
||||
*/
|
||||
.globl trap_reloc
|
||||
.type trap_reloc, @function
|
||||
trap_reloc:
|
||||
lwz r0, 0(r7) /* hdlr ... */
|
||||
add r0, r0, r3 /* ... += dest_addr */
|
||||
stw r0, 0(r7)
|
||||
|
||||
lwz r0, 4(r7) /* int_return ... */
|
||||
add r0, r0, r3 /* ... += dest_addr */
|
||||
stw r0, 4(r7)
|
||||
|
||||
lwz r0, 8(r7) /* transfer_to_handler ...*/
|
||||
add r0, r0, r3 /* ... += dest_addr */
|
||||
stw r0, 8(r7)
|
||||
|
||||
blr
|
||||
.size trap_reloc, .-trap_reloc
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2012 Stefan Roese <sr@denx.de>
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <spl.h>
|
||||
#include <image.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
/*
|
||||
* This function jumps to an image with argument. Normally an FDT or ATAGS
|
||||
* image.
|
||||
*/
|
||||
#ifdef CONFIG_SPL_OS_BOOT
|
||||
void __noreturn jump_to_image_linux(struct spl_image_info *spl_image)
|
||||
{
|
||||
debug("Entering kernel arg pointer: 0x%p\n", spl_image->arg);
|
||||
typedef void (*image_entry_arg_t)(void *, ulong r4, ulong r5, ulong r6,
|
||||
ulong r7, ulong r8, ulong r9)
|
||||
__attribute__ ((noreturn));
|
||||
image_entry_arg_t image_entry =
|
||||
(image_entry_arg_t)spl_image->entry_point;
|
||||
|
||||
image_entry(spl_image->arg, 0, 0, EPAPR_MAGIC, CONFIG_SYS_BOOTMAPSZ,
|
||||
0, 0);
|
||||
}
|
||||
#endif /* CONFIG_SPL_OS_BOOT */
|
||||
@@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2015 Andreas Bießmann <andreas@biessmann.org>
|
||||
*
|
||||
* Copyright (c) 2011 The Chromium OS Authors.
|
||||
* (C) Copyright 2002-2006
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Marius Groeger <mgroeger@sysgo.de>
|
||||
*/
|
||||
#include <common.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int arch_reserve_stacks(void)
|
||||
{
|
||||
ulong *s;
|
||||
|
||||
/* setup stack pointer for exceptions */
|
||||
gd->irq_sp = gd->start_addr_sp;
|
||||
|
||||
/* Clear initial stack frame */
|
||||
s = (ulong *)gd->start_addr_sp;
|
||||
*s = 0; /* Terminate back chain */
|
||||
*++s = 0; /* NULL return address */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2000, 2001
|
||||
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
|
||||
* base on code by
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*/
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
#include <config.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
/*
|
||||
* unsigned long long get_ticks(void);
|
||||
*
|
||||
* read timebase as "long long"
|
||||
*/
|
||||
.globl get_ticks
|
||||
get_ticks:
|
||||
1: mftbu r3
|
||||
mftb r4
|
||||
mftbu r5
|
||||
cmp 0,r3,r5
|
||||
bne 1b
|
||||
blr
|
||||
|
||||
/*
|
||||
* Delay for a number of ticks
|
||||
*/
|
||||
.globl wait_ticks
|
||||
wait_ticks:
|
||||
stwu r1, -16(r1)
|
||||
mflr r0 /* save link register */
|
||||
stw r0, 20(r1) /* Use r0 or GDB will be unhappy */
|
||||
stw r14, 12(r1) /* save used registers */
|
||||
stw r15, 8(r1)
|
||||
mr r14, r3 /* save tick count */
|
||||
bl get_ticks /* Get start time */
|
||||
|
||||
/* Calculate end time */
|
||||
addc r14, r4, r14 /* Compute end time lower */
|
||||
addze r15, r3 /* and end time upper */
|
||||
|
||||
WATCHDOG_RESET /* Trigger watchdog, if needed */
|
||||
1: bl get_ticks /* Get current time */
|
||||
subfc r4, r4, r14 /* Subtract current time from end time */
|
||||
subfe. r3, r3, r15
|
||||
bge 1b /* Loop until time expired */
|
||||
|
||||
lwz r15, 8(r1) /* restore saved registers */
|
||||
lwz r14, 12(r1)
|
||||
lwz r0, 20(r1)
|
||||
addi r1,r1,16
|
||||
mtlr r0
|
||||
blr
|
||||
@@ -0,0 +1,74 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2000, 2001
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <time.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* This function is intended for SHORT delays only.
|
||||
* It will overflow at around 10 seconds @ 400MHz,
|
||||
* or 20 seconds @ 200MHz.
|
||||
*/
|
||||
unsigned long usec2ticks(unsigned long usec)
|
||||
{
|
||||
ulong ticks;
|
||||
|
||||
if (usec < 1000) {
|
||||
ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
|
||||
} else {
|
||||
ticks = ((usec / 10) * (get_tbclk() / 100000));
|
||||
}
|
||||
|
||||
return (ticks);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* We implement the delay by converting the delay (the number of
|
||||
* microseconds to wait) into a number of time base ticks; then we
|
||||
* watch the time base until it has incremented by that amount.
|
||||
*/
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
ulong ticks = usec2ticks (usec);
|
||||
wait_ticks (ticks);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#ifndef CONFIG_NAND_SPL
|
||||
unsigned long ticks2usec(unsigned long ticks)
|
||||
{
|
||||
ulong tbclk = get_tbclk();
|
||||
|
||||
/* usec = ticks * 1000000 / tbclk
|
||||
* Multiplication would overflow at ~4.2e3 ticks,
|
||||
* so we break it up into
|
||||
* usec = ( ( ticks * 1000) / tbclk ) * 1000;
|
||||
*/
|
||||
ticks *= 1000L;
|
||||
ticks /= tbclk;
|
||||
ticks *= 1000L;
|
||||
|
||||
return ((ulong)ticks);
|
||||
}
|
||||
#endif
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
/* reset */
|
||||
asm volatile("li %0,0 ; mttbl %0 ; mttbu %0;"
|
||||
: "=&r"(temp) );
|
||||
|
||||
return (0);
|
||||
}
|
||||
/* ------------------------------------------------------------------------- */
|
||||
Reference in New Issue
Block a user