GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2000-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
## Build a couple of necessary functions into a private libgcc
## if the user asked for it
lib-$(CONFIG_USE_PRIVATE_LIBGCC) += lshrdi3.o muldi3.o ashldi3.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o
obj-y += cache.o
obj-y += interrupts.o
obj-y += time.o
obj-y += traps.o
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* ashldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
* gcc-2.7.2.3/longlong.h
*
* Copyright (C) 1989-2015 Free Software Foundation, Inc.
*/
#define BITS_PER_UNIT 8
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
struct DIstruct {SItype high, low;};
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
DItype __ashldi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.low = 0;
w.s.high = (USItype)uu.s.low << -bm;
}
else
{
USItype carries = (USItype)uu.s.low >> bm;
w.s.low = (USItype)uu.s.low << b;
w.s.high = ((USItype)uu.s.high << b) | carries;
}
return w.ll;
}
@@ -0,0 +1,121 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <common.h>
#include <command.h>
#include <env.h>
#include <image.h>
#include <u-boot/zlib.h>
#include <bzlib.h>
#include <watchdog.h>
#include <asm/byteorder.h>
#ifdef CONFIG_SHOW_BOOT_PROGRESS
# include <status_led.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
#define PHYSADDR(x) x
#define LINUX_MAX_ENVS 256
#define LINUX_MAX_ARGS 256
static ulong get_sp (void);
static void set_clocks_in_mhz (bd_t *kbd);
void arch_lmb_reserve(struct lmb *lmb)
{
ulong sp;
/*
* 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 ", sp);
/* adjust sp by 1K to be safe */
sp -= 1024;
lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp));
}
int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
{
int ret;
bd_t *kbd;
void (*kernel) (bd_t *, ulong, ulong, ulong, ulong);
struct lmb *lmb = &images->lmb;
/*
* allow the PREP bootm subcommand, it is required for bootm to work
*/
if (flag & BOOTM_STATE_OS_PREP)
return 0;
if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
return 1;
/* allocate space for kernel copy of board info */
ret = boot_get_kbd (lmb, &kbd);
if (ret) {
puts("ERROR with allocation of kernel bd\n");
goto error;
}
set_clocks_in_mhz(kbd);
ret = image_setup_linux(images);
if (ret)
goto error;
kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))images->ep;
debug("## Transferring control to Linux (at address %08lx) ...\n",
(ulong) kernel);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
/*
* Linux Kernel Parameters (passing board info data):
* sp+00: Ignore, side effect of using jsr to jump to kernel
* sp+04: ptr to board info data
* sp+08: initrd_start or 0 if no initrd
* sp+12: initrd_end - unused if initrd_start is 0
* sp+16: Start of command line string
* sp+20: End of command line string
*/
(*kernel)(kbd, images->initrd_start, images->initrd_end,
images->cmdline_start, images->cmdline_end);
/* does not return */
error:
return 1;
}
static ulong get_sp (void)
{
ulong sp;
asm("movel %%a7, %%d0\n"
"movel %%d0, %0\n": "=d"(sp): :"%d0");
return sp;
}
static void set_clocks_in_mhz (bd_t *kbd)
{
char *s;
s = env_get("clocks_in_mhz");
if (s) {
/* convert all clock information to MHz */
kbd->bi_intfreq /= 1000000L;
kbd->bi_busfreq /= 1000000L;
}
}
@@ -0,0 +1,144 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <common.h>
#include <cpu_func.h>
#include <asm/immap.h>
#include <asm/cache.h>
volatile int *cf_icache_status = (int *)ICACHE_STATUS;
volatile int *cf_dcache_status = (int *)DCACHE_STATUS;
void flush_cache(ulong start_addr, ulong size)
{
/* Must be implemented for all M68k processors with copy-back data cache */
}
int icache_status(void)
{
return *cf_icache_status;
}
int dcache_status(void)
{
return *cf_dcache_status;
}
void icache_enable(void)
{
icache_invalid();
*cf_icache_status = 1;
#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr2"::"r"(CONFIG_SYS_CACHE_ACR2));
__asm__ __volatile__("movec %0, %%acr3"::"r"(CONFIG_SYS_CACHE_ACR3));
#if defined(CONFIG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr6"::"r"(CONFIG_SYS_CACHE_ACR6));
__asm__ __volatile__("movec %0, %%acr7"::"r"(CONFIG_SYS_CACHE_ACR7));
#endif
#else
__asm__ __volatile__("movec %0, %%acr0"::"r"(CONFIG_SYS_CACHE_ACR0));
__asm__ __volatile__("movec %0, %%acr1"::"r"(CONFIG_SYS_CACHE_ACR1));
#endif
__asm__ __volatile__("movec %0, %%cacr"::"r"(CONFIG_SYS_CACHE_ICACR));
}
void icache_disable(void)
{
u32 temp = 0;
*cf_icache_status = 0;
icache_invalid();
#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr2"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr3"::"r"(temp));
#if defined(CONFIG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr6"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr7"::"r"(temp));
#endif
#else
__asm__ __volatile__("movec %0, %%acr0"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr1"::"r"(temp));
#endif
}
void icache_invalid(void)
{
u32 temp;
temp = CONFIG_SYS_ICACHE_INV;
if (*cf_icache_status)
temp |= CONFIG_SYS_CACHE_ICACR;
__asm__ __volatile__("movec %0, %%cacr"::"r"(temp));
}
/*
* data cache only for ColdFire V4 such as MCF547x_8x, MCF5445x
* the dcache will be dummy in ColdFire V2 and V3
*/
void dcache_enable(void)
{
dcache_invalid();
*cf_dcache_status = 1;
#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr0"::"r"(CONFIG_SYS_CACHE_ACR0));
__asm__ __volatile__("movec %0, %%acr1"::"r"(CONFIG_SYS_CACHE_ACR1));
#if defined(CONFIG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr4"::"r"(CONFIG_SYS_CACHE_ACR4));
__asm__ __volatile__("movec %0, %%acr5"::"r"(CONFIG_SYS_CACHE_ACR5));
#endif
#endif
__asm__ __volatile__("movec %0, %%cacr"::"r"(CONFIG_SYS_CACHE_DCACR));
}
void dcache_disable(void)
{
u32 temp = 0;
*cf_dcache_status = 0;
dcache_invalid();
__asm__ __volatile__("movec %0, %%cacr"::"r"(temp));
#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr0"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr1"::"r"(temp));
#if defined(CONFIG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr4"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr5"::"r"(temp));
#endif
#endif
}
void dcache_invalid(void)
{
#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
u32 temp;
temp = CONFIG_SYS_DCACHE_INV;
if (*cf_dcache_status)
temp |= CONFIG_SYS_CACHE_DCACR;
if (*cf_icache_status)
temp |= CONFIG_SYS_CACHE_ICACR;
__asm__ __volatile__("movec %0, %%cacr"::"r"(temp));
#endif
}
__weak void invalidate_dcache_range(unsigned long start, unsigned long stop)
{
/* An empty stub, real implementation should be in platform code */
}
__weak void flush_dcache_range(unsigned long start, unsigned long stop)
{
/* An empty stub, real implementation should be in platform code */
}
@@ -0,0 +1,99 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2000-2004
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* (C) Copyright 2007 Freescale Semiconductor Inc
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
*/
#include <common.h>
#include <irq_func.h>
#include <watchdog.h>
#include <asm/processor.h>
#include <asm/immap.h>
#define NR_IRQS (CONFIG_SYS_NUM_IRQS)
/*
* Interrupt vector functions.
*/
struct interrupt_action {
interrupt_handler_t *handler;
void *arg;
};
static struct interrupt_action irq_vecs[NR_IRQS];
static __inline__ unsigned short get_sr (void)
{
unsigned short sr;
asm volatile ("move.w %%sr,%0":"=r" (sr):);
return sr;
}
static __inline__ void set_sr (unsigned short sr)
{
asm volatile ("move.w %0,%%sr"::"r" (sr));
}
/************************************************************************/
/*
* Install and free an interrupt handler
*/
void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
{
if ((vec < 0) || (vec >= NR_IRQS)) {
printf ("irq_install_handler: wrong interrupt vector %d\n",
vec);
return;
}
irq_vecs[vec].handler = handler;
irq_vecs[vec].arg = arg;
}
void irq_free_handler(int vec)
{
if ((vec < 0) || (vec >= NR_IRQS)) {
return;
}
irq_vecs[vec].handler = NULL;
irq_vecs[vec].arg = NULL;
}
void enable_interrupts(void)
{
unsigned short sr;
sr = get_sr ();
set_sr (sr & ~0x0700);
}
int disable_interrupts(void)
{
unsigned short sr;
sr = get_sr ();
set_sr (sr | 0x0700);
return ((sr & 0x0700) == 0); /* return true, if interrupts were enabled before */
}
void int_handler (struct pt_regs *fp)
{
int vec;
vec = (fp->vector >> 2) & 0xff;
if (vec > 0x40)
vec -= 0x40;
if (irq_vecs[vec].handler != NULL) {
irq_vecs[vec].handler (irq_vecs[vec].arg);
} else {
printf ("\nBogus External Interrupt Vector %d\n", vec);
}
}
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* lshrdi3.c extracted from gcc-2.7.2.3/libgcc2.c and
* gcc-2.7.2.3/longlong.h
*
* Copyright (C) 1989-2015 Free Software Foundation, Inc.
*/
#define BITS_PER_UNIT 8
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
struct DIstruct {SItype high, low;};
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
DItype __lshrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.high = 0;
w.s.low = (USItype)uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = (USItype)uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
return w.ll;
}
@@ -0,0 +1,70 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
* gcc-2.7.2.3/longlong.h
*
* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
*/
#define SI_TYPE_SIZE 32
#define __BITS4 (SI_TYPE_SIZE / 4)
#define __ll_B (1L << (SI_TYPE_SIZE / 2))
#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
#define __ll_highpart(t) ((USItype) (t) / __ll_B)
#define umul_ppmm(w1, w0, u, v) \
do { \
USItype __x0, __x1, __x2, __x3; \
USItype __ul, __vl, __uh, __vh; \
\
__ul = __ll_lowpart (u); \
__uh = __ll_highpart (u); \
__vl = __ll_lowpart (v); \
__vh = __ll_highpart (v); \
\
__x0 = (USItype) __ul * __vl; \
__x1 = (USItype) __ul * __vh; \
__x2 = (USItype) __uh * __vl; \
__x3 = (USItype) __uh * __vh; \
\
__x1 += __ll_highpart (__x0);/* this can't give carry */ \
__x1 += __x2; /* but this indeed can */ \
if (__x1 < __x2) /* did we get it? */ \
__x3 += __ll_B; /* yes, add it in the proper pos. */ \
\
(w1) = __x3 + __ll_highpart (__x1); \
(w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
} while (0)
#define __umulsidi3(u, v) \
({DIunion __w; \
umul_ppmm (__w.s.high, __w.s.low, u, v); \
__w.ll; })
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
struct DIstruct {SItype high, low;};
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
DItype __muldi3 (DItype u, DItype v)
{
DIunion w;
DIunion uu, vv;
uu.ll = u,
vv.ll = v;
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+ (USItype) uu.s.high * (USItype) vv.s.low);
return w.ll;
}
@@ -0,0 +1,197 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <common.h>
#include <irq_func.h>
#include <time.h>
#include <asm/timer.h>
#include <asm/immap.h>
#include <watchdog.h>
DECLARE_GLOBAL_DATA_PTR;
static volatile ulong timestamp = 0;
#ifndef CONFIG_SYS_WATCHDOG_FREQ
#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
#endif
#if defined(CONFIG_MCFTMR)
#ifndef CONFIG_SYS_UDELAY_BASE
# error "uDelay base not defined!"
#endif
#if !defined(CONFIG_SYS_TMR_BASE) || !defined(CONFIG_SYS_INTR_BASE) || !defined(CONFIG_SYS_TMRINTR_NO) || !defined(CONFIG_SYS_TMRINTR_MASK)
# error "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
#endif
extern void dtimer_intr_setup(void);
void __udelay(unsigned long usec)
{
volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_UDELAY_BASE);
uint start, now, tmp;
while (usec > 0) {
if (usec > 65000)
tmp = 65000;
else
tmp = usec;
usec = usec - tmp;
/* Set up TIMER 3 as timebase clock */
timerp->tmr = DTIM_DTMR_RST_RST;
timerp->tcn = 0;
/* set period to 1 us */
timerp->tmr =
CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
DTIM_DTMR_RST_EN;
start = now = timerp->tcn;
while (now < start + tmp)
now = timerp->tcn;
}
}
void dtimer_interrupt(void *not_used)
{
volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
/* check for timer interrupt asserted */
if ((CONFIG_SYS_TMRPND_REG & CONFIG_SYS_TMRINTR_MASK) == CONFIG_SYS_TMRINTR_PEND) {
timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
timestamp++;
#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0) {
WATCHDOG_RESET ();
}
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
return;
}
}
int timer_init(void)
{
volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
timestamp = 0;
timerp->tcn = 0;
timerp->trr = 0;
/* Set up TIMER 4 as clock */
timerp->tmr = DTIM_DTMR_RST_RST;
/* initialize and enable timer interrupt */
irq_install_handler(CONFIG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
timerp->tcn = 0;
timerp->trr = 1000; /* Interrupt every ms */
dtimer_intr_setup();
/* set a period of 1us, set timer mode to restart and enable timer and interrupt */
timerp->tmr = CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
return 0;
}
ulong get_timer(ulong base)
{
return (timestamp - base);
}
#endif /* CONFIG_MCFTMR */
#if defined(CONFIG_MCFPIT)
#if !defined(CONFIG_SYS_PIT_BASE)
# error "CONFIG_SYS_PIT_BASE not defined!"
#endif
static unsigned short lastinc;
void __udelay(unsigned long usec)
{
volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_UDELAY_BASE);
uint tmp;
while (usec > 0) {
if (usec > 65000)
tmp = 65000;
else
tmp = usec;
usec = usec - tmp;
/* Set up TIMER 3 as timebase clock */
timerp->pcsr = PIT_PCSR_OVW;
timerp->pmr = 0;
/* set period to 1 us */
timerp->pcsr |= PIT_PCSR_PRE(CONFIG_SYS_PIT_PRESCALE) | PIT_PCSR_EN;
timerp->pmr = tmp;
while (timerp->pcntr > 0) ;
}
}
void timer_init(void)
{
volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
timestamp = 0;
/* Set up TIMER 4 as poll clock */
timerp->pcsr = PIT_PCSR_OVW;
timerp->pmr = lastinc = 0;
timerp->pcsr |= PIT_PCSR_PRE(CONFIG_SYS_PIT_PRESCALE) | PIT_PCSR_EN;
return 0;
}
ulong get_timer(ulong base)
{
unsigned short now, diff;
volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
now = timerp->pcntr;
diff = -(now - lastinc);
timestamp += diff;
lastinc = now;
return timestamp - base;
}
void wait_ticks(unsigned long ticks)
{
u32 start = get_timer(0);
while (get_timer(start) < ticks) ;
}
#endif /* CONFIG_MCFPIT */
/*
* This function is derived from PowerPC code (read timebase as long long).
* On M68K it just returns the timer value.
*/
unsigned long long get_ticks(void)
{
return get_timer(0);
}
unsigned long usec2ticks(unsigned long usec)
{
return get_timer(usec);
}
/*
* This function is derived from PowerPC code (timebase clock frequency).
* On M68K it returns the number of timer ticks per second.
*/
ulong get_tbclk(void)
{
return CONFIG_SYS_HZ;
}
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2003
* Josef Baumgartner <josef.baumgartner@telex.de>
*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <common.h>
#include <init.h>
#include <watchdog.h>
#include <command.h>
#include <asm/processor.h>
extern void _exc_handler(void);
extern void _int_handler(void);
static void show_frame(struct pt_regs *fp)
{
printf ("Vector Number: %d Format: %02x Fault Status: %01x\n\n", (fp->vector & 0x3fc) >> 2,
fp->format, (fp->vector & 0x3) | ((fp->vector & 0xc00) >> 8));
printf ("PC: %08lx SR: %08lx SP: %08lx\n", fp->pc, (long) fp->sr, (long) fp);
printf ("D0: %08lx D1: %08lx D2: %08lx D3: %08lx\n",
fp->d0, fp->d1, fp->d2, fp->d3);
printf ("D4: %08lx D5: %08lx D6: %08lx D7: %08lx\n",
fp->d4, fp->d5, fp->d6, fp->d7);
printf ("A0: %08lx A1: %08lx A2: %08lx A3: %08lx\n",
fp->a0, fp->a1, fp->a2, fp->a3);
printf ("A4: %08lx A5: %08lx A6: %08lx\n",
fp->a4, fp->a5, fp->a6);
}
void exc_handler(struct pt_regs *fp) {
printf("\n\n*** Unexpected exception ***\n");
show_frame (fp);
printf("\n*** Please Reset Board! ***\n");
for(;;);
}
void trap_init(ulong value) {
unsigned long *vec = (ulong *)value;
int i;
for(i = 2; i < 25; i++) {
vec[i] = (unsigned long)_exc_handler;
}
for(i = 25; i < 32; i++) {
vec[i] = (unsigned long)_int_handler;
}
for(i = 32; i < 64; i++) {
vec[i] = (unsigned long)_exc_handler;
}
for(i = 64; i < 256; i++) {
vec[i] = (unsigned long)_int_handler;
}
setvbr(value); /* set vector base register to new table */
}