avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
62
u-boot/arch/powerpc/lib/Makefile
Normal file
62
u-boot/arch/powerpc/lib/Makefile
Normal file
@@ -0,0 +1,62 @@
|
||||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
## 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
|
||||
obj-y += ticks.o
|
||||
else
|
||||
|
||||
obj-y += ppcstring.o
|
||||
|
||||
obj-y += ppccache.o
|
||||
obj-y += ticks.o
|
||||
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-$(CONFIG_CMD_IDE) += ide.o
|
||||
obj-y += stack.o
|
||||
obj-y += time.o
|
||||
|
||||
# Don't include the MPC5xxx special memcpy into the
|
||||
# SPL U-Boot image. memcpy is used in the SPL NOR
|
||||
# flash driver. And we need the real, fast memcpy
|
||||
# here. We have no problems with unaligned access.
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
# Workaround for local bus unaligned access problems
|
||||
# on MPC512x and MPC5200
|
||||
ifdef CONFIG_MPC512X
|
||||
AFLAGS_ppcstring.o += -Dmemcpy=__memcpy
|
||||
obj-y += memcpy_mpc5200.o
|
||||
endif
|
||||
ifdef CONFIG_MPC5200
|
||||
AFLAGS_ppcstring.o += -Dmemcpy=__memcpy
|
||||
obj-y += memcpy_mpc5200.o
|
||||
endif
|
||||
endif
|
||||
|
||||
endif # not minimal
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
|
||||
endif
|
||||
42
u-boot/arch/powerpc/lib/_ashldi3.S
Normal file
42
u-boot/arch/powerpc/lib/_ashldi3.S
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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
|
||||
44
u-boot/arch/powerpc/lib/_ashrdi3.S
Normal file
44
u-boot/arch/powerpc/lib/_ashrdi3.S
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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
|
||||
42
u-boot/arch/powerpc/lib/_lshrdi3.S
Normal file
42
u-boot/arch/powerpc/lib/_lshrdi3.S
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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
|
||||
244
u-boot/arch/powerpc/lib/bat_rw.c
Normal file
244
u-boot/arch/powerpc/lib/bat_rw.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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
|
||||
}
|
||||
341
u-boot/arch/powerpc/lib/bootm.c
Normal file
341
u-boot/arch/powerpc/lib/bootm.c
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* (C) Copyright 2008 Semihalf
|
||||
*
|
||||
* (C) Copyright 2000-2006
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
|
||||
#include <common.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
#include <malloc.h>
|
||||
#include <u-boot/zlib.h>
|
||||
#include <bzlib.h>
|
||||
#include <environment.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/mp.h>
|
||||
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
#include <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,
|
||||
getenv_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 = getenv_bootm_low();
|
||||
bootm_size = getenv_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;
|
||||
|
||||
if ((s = getenv ("clocks_in_mhz")) != NULL) {
|
||||
/* 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_MPC5xxx)
|
||||
kbd->bi_ipbfreq /= 1000000L;
|
||||
kbd->bi_pcifreq /= 1000000L;
|
||||
#endif /* CONFIG_MPC5xxx */
|
||||
}
|
||||
}
|
||||
|
||||
#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, getenv_bootm_mapsize(), 0, 0);
|
||||
}
|
||||
#endif
|
||||
37
u-boot/arch/powerpc/lib/cache.c
Normal file
37
u-boot/arch/powerpc/lib/cache.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.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
|
||||
}
|
||||
64
u-boot/arch/powerpc/lib/extable.c
Normal file
64
u-boot/arch/powerpc/lib/extable.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
|
||||
*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#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.
|
||||
*/
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
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;
|
||||
}
|
||||
184
u-boot/arch/powerpc/lib/ide.c
Normal file
184
u-boot/arch/powerpc/lib/ide.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2011
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/* Code taken from cmd_ide.c */
|
||||
#include <common.h>
|
||||
#include <ata.h>
|
||||
#include "ide.h"
|
||||
|
||||
#ifdef CONFIG_IDE_8xx_DIRECT
|
||||
#include <mpc8xx.h>
|
||||
#include <pcmcia.h>
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* Timings for IDE Interface
|
||||
*
|
||||
* SETUP / LENGTH / HOLD - cycles valid for 50 MHz clk
|
||||
* 70 165 30 PIO-Mode 0, [ns]
|
||||
* 4 9 2 [Cycles]
|
||||
* 50 125 20 PIO-Mode 1, [ns]
|
||||
* 3 7 2 [Cycles]
|
||||
* 30 100 15 PIO-Mode 2, [ns]
|
||||
* 2 6 1 [Cycles]
|
||||
* 30 80 10 PIO-Mode 3, [ns]
|
||||
* 2 5 1 [Cycles]
|
||||
* 25 70 10 PIO-Mode 4, [ns]
|
||||
* 2 4 1 [Cycles]
|
||||
*/
|
||||
|
||||
static const pio_config_t pio_config_ns[IDE_MAX_PIO_MODE+1] = {
|
||||
/* Setup Length Hold */
|
||||
{ 70, 165, 30 }, /* PIO-Mode 0, [ns] */
|
||||
{ 50, 125, 20 }, /* PIO-Mode 1, [ns] */
|
||||
{ 30, 101, 15 }, /* PIO-Mode 2, [ns] */
|
||||
{ 30, 80, 10 }, /* PIO-Mode 3, [ns] */
|
||||
{ 25, 70, 10 }, /* PIO-Mode 4, [ns] */
|
||||
};
|
||||
|
||||
static pio_config_t pio_config_clk[IDE_MAX_PIO_MODE+1];
|
||||
|
||||
#ifndef CONFIG_SYS_PIO_MODE
|
||||
#define CONFIG_SYS_PIO_MODE 0 /* use a relaxed default */
|
||||
#endif
|
||||
static int pio_mode = CONFIG_SYS_PIO_MODE;
|
||||
|
||||
/* Make clock cycles and always round up */
|
||||
|
||||
#define PCMCIA_MK_CLKS(t, T) (((t) * (T) + 999U) / 1000U)
|
||||
|
||||
static void set_pcmcia_timing(int pmode)
|
||||
{
|
||||
volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
|
||||
volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
|
||||
ulong timings;
|
||||
|
||||
debug("Set timing for PIO Mode %d\n", pmode);
|
||||
|
||||
timings = PCMCIA_SHT(pio_config_clk[pmode].t_hold)
|
||||
| PCMCIA_SST(pio_config_clk[pmode].t_setup)
|
||||
| PCMCIA_SL(pio_config_clk[pmode].t_length);
|
||||
|
||||
/*
|
||||
* IDE 0
|
||||
*/
|
||||
pcmp->pcmc_pbr0 = CONFIG_SYS_PCMCIA_PBR0;
|
||||
#if (CONFIG_SYS_PCMCIA_POR0 != 0)
|
||||
pcmp->pcmc_por0 = CONFIG_SYS_PCMCIA_POR0 | timings;
|
||||
#else
|
||||
pcmp->pcmc_por0 = CONFIG_SYS_PCMCIA_POR0;
|
||||
#endif
|
||||
debug("PBR0: %08x POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0);
|
||||
|
||||
pcmp->pcmc_pbr1 = CONFIG_SYS_PCMCIA_PBR1;
|
||||
#if (CONFIG_SYS_PCMCIA_POR1 != 0)
|
||||
pcmp->pcmc_por1 = CONFIG_SYS_PCMCIA_POR1 | timings;
|
||||
#else
|
||||
pcmp->pcmc_por1 = CONFIG_SYS_PCMCIA_POR1;
|
||||
#endif
|
||||
debug("PBR1: %08x POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1);
|
||||
|
||||
pcmp->pcmc_pbr2 = CONFIG_SYS_PCMCIA_PBR2;
|
||||
#if (CONFIG_SYS_PCMCIA_POR2 != 0)
|
||||
pcmp->pcmc_por2 = CONFIG_SYS_PCMCIA_POR2 | timings;
|
||||
#else
|
||||
pcmp->pcmc_por2 = CONFIG_SYS_PCMCIA_POR2;
|
||||
#endif
|
||||
debug("PBR2: %08x POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2);
|
||||
|
||||
pcmp->pcmc_pbr3 = CONFIG_SYS_PCMCIA_PBR3;
|
||||
#if (CONFIG_SYS_PCMCIA_POR3 != 0)
|
||||
pcmp->pcmc_por3 = CONFIG_SYS_PCMCIA_POR3 | timings;
|
||||
#else
|
||||
pcmp->pcmc_por3 = CONFIG_SYS_PCMCIA_POR3;
|
||||
#endif
|
||||
debug("PBR3: %08x POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3);
|
||||
|
||||
/*
|
||||
* IDE 1
|
||||
*/
|
||||
pcmp->pcmc_pbr4 = CONFIG_SYS_PCMCIA_PBR4;
|
||||
#if (CONFIG_SYS_PCMCIA_POR4 != 0)
|
||||
pcmp->pcmc_por4 = CONFIG_SYS_PCMCIA_POR4 | timings;
|
||||
#else
|
||||
pcmp->pcmc_por4 = CONFIG_SYS_PCMCIA_POR4;
|
||||
#endif
|
||||
debug("PBR4: %08x POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4);
|
||||
|
||||
pcmp->pcmc_pbr5 = CONFIG_SYS_PCMCIA_PBR5;
|
||||
#if (CONFIG_SYS_PCMCIA_POR5 != 0)
|
||||
pcmp->pcmc_por5 = CONFIG_SYS_PCMCIA_POR5 | timings;
|
||||
#else
|
||||
pcmp->pcmc_por5 = CONFIG_SYS_PCMCIA_POR5;
|
||||
#endif
|
||||
debug("PBR5: %08x POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5);
|
||||
|
||||
pcmp->pcmc_pbr6 = CONFIG_SYS_PCMCIA_PBR6;
|
||||
#if (CONFIG_SYS_PCMCIA_POR6 != 0)
|
||||
pcmp->pcmc_por6 = CONFIG_SYS_PCMCIA_POR6 | timings;
|
||||
#else
|
||||
pcmp->pcmc_por6 = CONFIG_SYS_PCMCIA_POR6;
|
||||
#endif
|
||||
debug("PBR6: %08x POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6);
|
||||
|
||||
pcmp->pcmc_pbr7 = CONFIG_SYS_PCMCIA_PBR7;
|
||||
#if (CONFIG_SYS_PCMCIA_POR7 != 0)
|
||||
pcmp->pcmc_por7 = CONFIG_SYS_PCMCIA_POR7 | timings;
|
||||
#else
|
||||
pcmp->pcmc_por7 = CONFIG_SYS_PCMCIA_POR7;
|
||||
#endif
|
||||
debug("PBR7: %08x POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7);
|
||||
|
||||
}
|
||||
|
||||
int ide_preinit(void)
|
||||
{
|
||||
int i;
|
||||
/* Initialize PIO timing tables */
|
||||
for (i = 0; i <= IDE_MAX_PIO_MODE; ++i) {
|
||||
pio_config_clk[i].t_setup =
|
||||
PCMCIA_MK_CLKS(pio_config_ns[i].t_setup, gd->bus_clk);
|
||||
pio_config_clk[i].t_length =
|
||||
PCMCIA_MK_CLKS(pio_config_ns[i].t_length, gd->bus_clk);
|
||||
pio_config_clk[i].t_hold =
|
||||
PCMCIA_MK_CLKS(pio_config_ns[i].t_hold, gd->bus_clk);
|
||||
debug("PIO Mode %d: setup=%2d ns/%d clk" " len=%3d ns/%d clk"
|
||||
" hold=%2d ns/%d clk\n", i, pio_config_ns[i].t_setup,
|
||||
pio_config_clk[i].t_setup, pio_config_ns[i].t_length,
|
||||
pio_config_clk[i].t_length, pio_config_ns[i].t_hold,
|
||||
pio_config_clk[i].t_hold);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ide_init_postreset(void)
|
||||
{
|
||||
volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
|
||||
volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
|
||||
|
||||
/* PCMCIA / IDE initialization for common mem space */
|
||||
pcmp->pcmc_pgcrb = 0;
|
||||
|
||||
/* start in PIO mode 0 - most relaxed timings */
|
||||
pio_mode = 0;
|
||||
set_pcmcia_timing(pio_mode);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IDE_8xx_DIRECT */
|
||||
|
||||
#ifdef CONFIG_IDE_8xx_PCCARD
|
||||
int ide_preinit(void)
|
||||
{
|
||||
ide_devices_found = 0;
|
||||
/* initialize the PCMCIA IDE adapter card */
|
||||
pcmcia_on();
|
||||
if (!ide_devices_found)
|
||||
return 1;
|
||||
udelay(1000000);/* 1 s */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
15
u-boot/arch/powerpc/lib/ide.h
Normal file
15
u-boot/arch/powerpc/lib/ide.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Pavel Herrmann <morpheus.ibis@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _MPC8XX_IDE_H_
|
||||
#define _MPC8XX_IDE_H_ 1
|
||||
|
||||
#ifdef CONFIG_IDE_8xx_PCCARD
|
||||
int pcmcia_on(void);
|
||||
extern int ide_devices_found;
|
||||
#endif
|
||||
#endif
|
||||
127
u-boot/arch/powerpc/lib/interrupts.c
Normal file
127
u-boot/arch/powerpc/lib/interrupts.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2003
|
||||
* Gleb Natapov <gnatapov@mrv.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
#include <watchdog.h>
|
||||
#ifdef CONFIG_STATUS_LED
|
||||
#include <status_led.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SHOW_ACTIVITY
|
||||
void board_show_activity (ulong) __attribute__((weak, alias("__board_show_activity")));
|
||||
|
||||
void __board_show_activity (ulong dummy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_SHOW_ACTIVITY */
|
||||
|
||||
#ifndef CONFIG_SYS_WATCHDOG_FREQ
|
||||
#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
|
||||
#endif
|
||||
|
||||
extern int interrupt_init_cpu (unsigned *);
|
||||
extern void timer_interrupt_cpu (struct pt_regs *);
|
||||
|
||||
static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
|
||||
|
||||
static __inline__ unsigned long get_msr (void)
|
||||
{
|
||||
unsigned long msr;
|
||||
|
||||
asm volatile ("mfmsr %0":"=r" (msr):);
|
||||
|
||||
return msr;
|
||||
}
|
||||
|
||||
static __inline__ void set_msr (unsigned long msr)
|
||||
{
|
||||
asm volatile ("mtmsr %0"::"r" (msr));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int interrupt_init (void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* call cpu specific function from $(CPU)/interrupts.c */
|
||||
ret = interrupt_init_cpu (&decrementer_count);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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_STATUS_LED
|
||||
status_led_tick (timestamp);
|
||||
#endif /* CONFIG_STATUS_LED */
|
||||
|
||||
#ifdef CONFIG_SHOW_ACTIVITY
|
||||
board_show_activity (timestamp);
|
||||
#endif /* CONFIG_SHOW_ACTIVITY */
|
||||
}
|
||||
|
||||
ulong get_timer (ulong base)
|
||||
{
|
||||
return (timestamp - base);
|
||||
}
|
||||
326
u-boot/arch/powerpc/lib/kgdb.c
Normal file
326
u-boot/arch/powerpc/lib/kgdb.c
Normal file
@@ -0,0 +1,326 @@
|
||||
#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));
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
get_msr(void)
|
||||
{
|
||||
unsigned long msr;
|
||||
asm volatile("mfmsr %0" : "=r" (msr):);
|
||||
return msr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_msr(unsigned long msr)
|
||||
{
|
||||
asm volatile("mtmsr %0" : : "r" (msr));
|
||||
}
|
||||
|
||||
/* 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 }, /* alingment */
|
||||
{ 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))
|
||||
|
||||
#ifdef CONFIG_MPC8260
|
||||
/* store floating double indexed */
|
||||
#define STFDI(n,p) __asm__ __volatile__ ("stfd " #n ",%0" : "=o"(p[2*n]))
|
||||
/* store floating double multiple */
|
||||
#define STFDM(p) { STFDI( 0,p); STFDI( 1,p); STFDI( 2,p); STFDI( 3,p); \
|
||||
STFDI( 4,p); STFDI( 5,p); STFDI( 6,p); STFDI( 7,p); \
|
||||
STFDI( 8,p); STFDI( 9,p); STFDI(10,p); STFDI(11,p); \
|
||||
STFDI(12,p); STFDI(13,p); STFDI(14,p); STFDI(15,p); \
|
||||
STFDI(16,p); STFDI(17,p); STFDI(18,p); STFDI(19,p); \
|
||||
STFDI(20,p); STFDI(21,p); STFDI(22,p); STFDI(23,p); \
|
||||
STFDI(24,p); STFDI(25,p); STFDI(26,p); STFDI(27,p); \
|
||||
STFDI(28,p); STFDI(29,p); STFDI(30,p); STFDI(31,p); }
|
||||
#endif
|
||||
|
||||
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 */
|
||||
#ifdef CONFIG_MPC8260
|
||||
STFDM(ptr);
|
||||
ptr += 32*2;
|
||||
#else
|
||||
for (i = 0; i < 32; i++) {
|
||||
*ptr++ = 0;
|
||||
*ptr++ = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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 */
|
||||
|
||||
#ifdef CONFIG_MPC8260
|
||||
/* load floating double */
|
||||
#define LFD(n,v) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"(v))
|
||||
/* load floating double indexed */
|
||||
#define LFDI(n,p) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"((p)[2*n]))
|
||||
/* load floating double multiple */
|
||||
#define LFDM(p) { LFDI( 0,p); LFDI( 1,p); LFDI( 2,p); LFDI( 3,p); \
|
||||
LFDI( 4,p); LFDI( 5,p); LFDI( 6,p); LFDI( 7,p); \
|
||||
LFDI( 8,p); LFDI( 9,p); LFDI(10,p); LFDI(11,p); \
|
||||
LFDI(12,p); LFDI(13,p); LFDI(14,p); LFDI(15,p); \
|
||||
LFDI(16,p); LFDI(17,p); LFDI(18,p); LFDI(19,p); \
|
||||
LFDI(20,p); LFDI(21,p); LFDI(22,p); LFDI(23,p); \
|
||||
LFDI(24,p); LFDI(25,p); LFDI(26,p); LFDI(27,p); \
|
||||
LFDI(28,p); LFDI(29,p); LFDI(30,p); LFDI(31,p); }
|
||||
#endif
|
||||
|
||||
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) {
|
||||
|
||||
#ifdef CONFIG_MPC8260
|
||||
#define caseF(n) \
|
||||
case (n) + 32: LFD(n, *ptr); break;
|
||||
|
||||
caseF( 0) caseF( 1) caseF( 2) caseF( 3) caseF( 4) caseF( 5) caseF( 6) caseF( 7)
|
||||
caseF( 8) caseF( 9) caseF(10) caseF(11) caseF(12) caseF(13) caseF(14) caseF(15)
|
||||
caseF(16) caseF(17) caseF(18) caseF(19) caseF(20) caseF(21) caseF(22) caseF(23)
|
||||
caseF(24) caseF(25) caseF(26) caseF(27) caseF(28) caseF(29) caseF(30) caseF(31)
|
||||
|
||||
#undef caseF
|
||||
#endif
|
||||
|
||||
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 */
|
||||
#ifdef CONFIG_MPC8260
|
||||
LFDM(ptr);
|
||||
#endif
|
||||
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\
|
||||
");
|
||||
}
|
||||
55
u-boot/arch/powerpc/lib/memcpy_mpc5200.c
Normal file
55
u-boot/arch/powerpc/lib/memcpy_mpc5200.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* (C) Copyright 2010
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a workaround for issues on the MPC5200, where unaligned
|
||||
* 32-bit-accesses to the local bus will deliver corrupted data. This
|
||||
* happens for example when trying to use memcpy() from an odd NOR
|
||||
* flash address; the behaviour can be also seen when using "md" on an
|
||||
* odd NOR flash address (but there it is not a bug in U-Boot, which
|
||||
* only shows the behaviour of this processor).
|
||||
*
|
||||
* For memcpy(), we test if either the source or the target address
|
||||
* are not 32 bit aligned, and - if so - if the source address is in
|
||||
* NOR flash: in this case we perform a byte-wise (slow) then; for
|
||||
* aligned operations of non-flash areas we use the optimized (fast)
|
||||
* real __memcpy(). This way we minimize the performance impact of
|
||||
* this workaround.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <flash.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
void *memcpy(void *trg, const void *src, size_t len)
|
||||
{
|
||||
extern void* __memcpy(void *, const void *, size_t);
|
||||
char *s = (char *)src;
|
||||
char *t = (char *)trg;
|
||||
void *dest = (void *)src;
|
||||
|
||||
/*
|
||||
* Check is source address is in flash:
|
||||
* If not, we use the fast assembler code
|
||||
*/
|
||||
if (((((unsigned long)s & 3) == 0) /* source aligned */
|
||||
&& /* AND */
|
||||
(((unsigned long)t & 3) == 0)) /* target aligned, */
|
||||
|| /* or */
|
||||
(addr2info((ulong)s) == NULL)) { /* source not in flash */
|
||||
return __memcpy(trg, src, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copying from flash, perform byte by byte copy.
|
||||
*/
|
||||
while (len-- > 0)
|
||||
*t++ = *s++;
|
||||
|
||||
return dest;
|
||||
}
|
||||
108
u-boot/arch/powerpc/lib/ppccache.S
Normal file
108
u-boot/arch/powerpc/lib/ppccache.S
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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_4xx) || 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_4xx) || 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
|
||||
|
||||
206
u-boot/arch/powerpc/lib/ppcstring.S
Normal file
206
u-boot/arch/powerpc/lib/ppcstring.S
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* String handling functions for PowerPC.
|
||||
*
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <asm/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
|
||||
33
u-boot/arch/powerpc/lib/reloc.S
Normal file
33
u-boot/arch/powerpc/lib/reloc.S
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Wolfgang Denk <wd@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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
|
||||
31
u-boot/arch/powerpc/lib/spl.c
Normal file
31
u-boot/arch/powerpc/lib/spl.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2012 Stefan Roese <sr@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <spl.h>
|
||||
#include <image.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* This function jumps to an image with argument. Normally an FDT or ATAGS
|
||||
* image.
|
||||
* arg: Pointer to paramter image in RAM
|
||||
*/
|
||||
#ifdef CONFIG_SPL_OS_BOOT
|
||||
void __noreturn jump_to_image_linux(void *arg)
|
||||
{
|
||||
debug("Entering kernel arg pointer: 0x%p\n", 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(arg, 0, 0, EPAPR_MAGIC, CONFIG_SYS_BOOTMAPSZ, 0, 0);
|
||||
}
|
||||
#endif /* CONFIG_SPL_OS_BOOT */
|
||||
31
u-boot/arch/powerpc/lib/stack.c
Normal file
31
u-boot/arch/powerpc/lib/stack.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#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;
|
||||
}
|
||||
57
u-boot/arch/powerpc/lib/ticks.S
Normal file
57
u-boot/arch/powerpc/lib/ticks.S
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* (C) Copyright 2000, 2001
|
||||
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
|
||||
* base on code by
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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
|
||||
84
u-boot/arch/powerpc/lib/time.c
Normal file
84
u-boot/arch/powerpc/lib/time.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* (C) Copyright 2000, 2001
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.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 init_timebase (void)
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
#if defined(CONFIG_5xx) || defined(CONFIG_8xx)
|
||||
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
|
||||
|
||||
/* unlock */
|
||||
immap->im_sitk.sitk_tbk = KAPWR_KEY;
|
||||
#endif
|
||||
|
||||
/* reset */
|
||||
asm volatile("li %0,0 ; mttbu %0 ; mttbl %0;"
|
||||
: "=&r"(temp) );
|
||||
|
||||
#if defined(CONFIG_5xx) || defined(CONFIG_8xx)
|
||||
/* enable */
|
||||
immap->im_sit.sit_tbscr |= TBSCR_TBE;
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
/* ------------------------------------------------------------------------- */
|
||||
Reference in New Issue
Block a user