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:
2026-03-03 21:46:32 +02:00
parent fe3ba02c96
commit 68d74d3181
11967 changed files with 2221897 additions and 0 deletions

View 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

View 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

View 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

View 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

View 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
}

View 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

View 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
}

View 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;
}

View 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

View 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

View 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);
}

View 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\
");
}

View 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;
}

View 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

View 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

View 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

View 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 */

View 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;
}

View 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

View 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);
}
/* ------------------------------------------------------------------------- */