diff options
Diffstat (limited to 'src/arch/ppc/lib')
-rw-r--r-- | src/arch/ppc/lib/c_start.S | 109 | ||||
-rw-r--r-- | src/arch/ppc/lib/floats.S | 45 | ||||
-rw-r--r-- | src/arch/ppc/lib/floats.inc | 43 | ||||
-rw-r--r-- | src/arch/ppc/lib/setup.c | 130 | ||||
-rw-r--r-- | src/arch/ppc/lib/timebase.S | 13 | ||||
-rw-r--r-- | src/arch/ppc/lib/timer.c | 31 |
6 files changed, 371 insertions, 0 deletions
diff --git a/src/arch/ppc/lib/c_start.S b/src/arch/ppc/lib/c_start.S new file mode 100644 index 0000000000..1719fd7103 --- /dev/null +++ b/src/arch/ppc/lib/c_start.S @@ -0,0 +1,109 @@ +/* $Id$ */ +/* Copyright 2000 AG Electronics Ltd. */ +/* This code is distributed without warranty under the GPL v2 (see COPYING) */ + +/* + * The assumption is that we're located in ROM and we have a fake stack + * located in cache. Our task is to turn on memory proper, the finish + * configuring the machine. + */ + +#define ASM +#include "ppcreg.h" +#include <ppc_asm.tmpl> + +.section ".text" +.globl _start + +_start: + /* + * init stack pointer to real ram now that memory is on + */ + lis r1, _estack@ha + addi r1, r1, _estack@l + stwu r0,-64(r1) + stwu r1,-24(r1) + + /* + * Clear stack + */ + lis r4, _stack@ha + addi r4, r4, _stack@l + lis r7, _estack@ha + addi r7, r7, _estack@l + lis r5, 0 +1: stwx r5, 0, r4 + addi r4, r4, 4 + cmp 0, 0, r4, r7 + ble 1b + sync + + /* + * Clear bss + */ + lis r4, _bss@ha + addi r4, r4, _bss@l + lis r7, _ebss@ha + addi r7, r7, _ebss@l + lis r5, 0 +1: stwx r5, 0, r4 + addi r4, r4, 4 + cmp 0, 0, r4, r7 + ble 1b + sync + + /* + * Set up the EABI pointers, before we enter any C code + */ + lis r13, _SDA_BASE_@ha + addi r13, r13, _SDA_BASE_@l + lis r2, _SDA2_BASE_@ha + addi r2, r2, _SDA2_BASE_@l + + /* + * load start address into SRR0 for rfi + */ + lis r3, hardwaremain@ha + addi r3, r3, hardwaremain@l + mtspr SRR0, r3 + + /* + * load the current MSR into SRR1 so that it will be copied + * back into MSR on rfi + */ + mfmsr r4 + mtspr SRR1, r4 // load SRR1 with r4 + + /* + * If something returns after rfi then die + */ + lis r3, dead@ha + addi r3, r3, dead@l + mtlr r3 + + /* + * Complete rest of initialization in C (hardwaremain) + */ + rfi + + /* + * Stop here if something goes wrong + */ +dead: + b dead + /*NOTREACHED*/ + +/* Remove need for ecrti.o and ectrn.o */ +.globl __init +__init: +.globl __fini +__fini: +.globl __CTOR_LIST__ +__CTOR_LIST__: +.globl __CTOR_END__ +__CTOR_END__: +.globl __DTOR_LIST__ +__DTOR_LIST__: +.globl __DTOR_END__ +__DTOR_END__: + blr diff --git a/src/arch/ppc/lib/floats.S b/src/arch/ppc/lib/floats.S new file mode 100644 index 0000000000..57b38cb9c3 --- /dev/null +++ b/src/arch/ppc/lib/floats.S @@ -0,0 +1,45 @@ +/* $Id$ */ +/* Copyright 1999-2000 AG Electronics Ltd. */ +/* This code is distributed without warranty under the GPL v2 (see COPYING) */ + +#include <ppc_asm.tmpl> + + .globl _init_float_registers + +_init_float_registers: + lfd fr0, 0(r3) + lfd fr1, 0(r3) + lfd fr2, 0(r3) + lfd fr3, 0(r3) + lfd fr4, 0(r3) + lfd fr5, 0(r3) + lfd fr6, 0(r3) + lfd fr7, 0(r3) + lfd fr8, 0(r3) + lfd fr9, 0(r3) + lfd fr10, 0(r3) + lfd fr11, 0(r3) + lfd fr12, 0(r3) + lfd fr13, 0(r3) + lfd fr14, 0(r3) + lfd fr15, 0(r3) + lfd fr16, 0(r3) + lfd fr17, 0(r3) + lfd fr18, 0(r3) + lfd fr19, 0(r3) + lfd fr20, 0(r3) + lfd fr21, 0(r3) + lfd fr22, 0(r3) + lfd fr23, 0(r3) + lfd fr24, 0(r3) + lfd fr25, 0(r3) + lfd fr26, 0(r3) + lfd fr27, 0(r3) + lfd fr28, 0(r3) + lfd fr29, 0(r3) + lfd fr30, 0(r3) + lfd fr31, 0(r3) + blr + + .end + diff --git a/src/arch/ppc/lib/floats.inc b/src/arch/ppc/lib/floats.inc new file mode 100644 index 0000000000..5c366af63f --- /dev/null +++ b/src/arch/ppc/lib/floats.inc @@ -0,0 +1,43 @@ +/* $Id$ */ +/* Copyright 1999-2000 AG Electronics Ltd. */ +/* This code is distributed without warranty under the GPL v2 (see COPYING) */ + +/* .text*/ + .globl _init_float_registers + +_init_float_registers: + lfd 0, 0(3) + lfd 1, 0(3) + lfd 2, 0(3) + lfd 3, 0(3) + lfd 4, 0(3) + lfd 5, 0(3) + lfd 6, 0(3) + lfd 7, 0(3) + lfd 8, 0(3) + lfd 9, 0(3) + lfd 10, 0(3) + lfd 11, 0(3) + lfd 12, 0(3) + lfd 13, 0(3) + lfd 14, 0(3) + lfd 15, 0(3) + lfd 16, 0(3) + lfd 17, 0(3) + lfd 18, 0(3) + lfd 19, 0(3) + lfd 20, 0(3) + lfd 21, 0(3) + lfd 22, 0(3) + lfd 23, 0(3) + lfd 24, 0(3) + lfd 25, 0(3) + lfd 26, 0(3) + lfd 27, 0(3) + lfd 28, 0(3) + lfd 29, 0(3) + lfd 30, 0(3) + lfd 31, 0(3) + blr + .end + diff --git a/src/arch/ppc/lib/setup.c b/src/arch/ppc/lib/setup.c new file mode 100644 index 0000000000..000a4b15a9 --- /dev/null +++ b/src/arch/ppc/lib/setup.c @@ -0,0 +1,130 @@ +/* $Id$ */ +/* Copyright 2000 AG Electronics Ltd. */ +/* This code is distributed without warranty under the GPL v2 (see COPYING) */ + +#include "ppc.h" +#include "ppcreg.h" + +unsigned __getmsr(void) +{ + unsigned result; + __asm__ volatile ("mfmsr %0" : "=r" (result)); + return result; +} + +unsigned __gethid0(void) +{ + unsigned result; + __asm__ volatile ("mfspr %0,1008" : "=r" (result)); + return result; +} + +unsigned __gethid1(void) +{ + unsigned result; + __asm__ volatile ("mfspr %0,1009" : "=r" (result)); + return result; +} + +void __sethid0(unsigned value) +{ + __asm__ volatile ("mtspr 1008,%0" : : "r" (value)); +} + +unsigned __getpvr(void) +{ + int result; + __asm__("mfspr %0, 287" : "=r" (result)); + return result; +} + +void __setmsr(unsigned value) +{ + __asm__ volatile ("mtmsr %0; sync" :: "r" (value)); +} + +void __set1015(unsigned value) +{ + __asm__ volatile ("mtspr 1015,%0" : : "r" (value)); +} + +extern void _init_float_registers(const double *); +/*RODATA static const double dummy_float = 1.0;*/ +static const double dummy_float = 1.0; + +#define HID0_DCACHE HID0_DCE +#define MSR_DATA MSR_DR + +void ppc_setup_cpu(int icache) +{ + int type = __getpvr() >> 16; + int version = __getpvr() & 0xffff; + + if (type == 0xc) + { + if (version == 0x0200) + __set1015(0x19000004); + else if (((version & 0xff00) == 0x0200) && + (version != 0x0209)) + __set1015(0x01000000); + } + if (icache) + { + __sethid0(HID0_NHR | HID0_BHT | HID0_ICE | HID0_ICFI | HID0_BTIC + | HID0_DCACHE); + __sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_ICE | HID0_BTIC + | HID0_DCACHE); + } + else + { + __sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_BTIC | HID0_DCACHE); + } +#if 1 + /* if (type == 8 || type == 12) */ + { + __setmsr(MSR_FP | MSR_DATA); + _init_float_registers(&dummy_float); + } +#endif +} + +void ppc_enable_dcache(void) +{ + /* + * Already enabled in crt0.S + */ +#if 0 + unsigned hid0 = __gethid0(); + __sethid0(hid0 | HID0_DCFI | HID0_DCE); + __sethid0(hid0 | HID0_DCE); +#endif +} + +void ppc_disable_dcache(void) +{ + unsigned hid0 = __gethid0(); + __sethid0(hid0 & ~HID0_DCE); +} + +void ppc_enable_mmu(void) +{ + unsigned msr = __getmsr(); + __setmsr(msr | MSR_DR | MSR_IR); +} + +void make_coherent(void *base, unsigned length) +{ + unsigned hid0 = __gethid0(); + + if (hid0 & HID0_DCE) + { + unsigned i; + unsigned offset = 0x1f & (unsigned) base; + unsigned adjusted_base = (unsigned) base & ~0x1f; + for(i = 0; i < length + offset; i+= 32) + __asm__ volatile ("dcbf %1,%0" : : "r" (adjusted_base), "r" (i)); + if (hid0 & HID0_ICE) + for(i = 0; i < length + offset; i+= 32) + __asm__ volatile ("icbi %1,%0" : : "r" (adjusted_base), "r" (i)); + } +} diff --git a/src/arch/ppc/lib/timebase.S b/src/arch/ppc/lib/timebase.S new file mode 100644 index 0000000000..48171db498 --- /dev/null +++ b/src/arch/ppc/lib/timebase.S @@ -0,0 +1,13 @@ +/* $Id$ */ +/* Copyright 1999-2000 AG Electronics Ltd. */ +/* This code is distributed without warranty under the GPL v2 (see COPYING) */ + + .text + .globl _timebase +_timebase: + mftbu 3 + mftb 4 + mftbu 5 + cmpw 3, 5 + bne _timebase + blr diff --git a/src/arch/ppc/lib/timer.c b/src/arch/ppc/lib/timer.c new file mode 100644 index 0000000000..8f968f1a5f --- /dev/null +++ b/src/arch/ppc/lib/timer.c @@ -0,0 +1,31 @@ +/* $Id$ */ +/* Copyright 2000 AG Electronics Ltd. */ +/* This code is distributed without warranty under the GPL v2 (see COPYING) */ + +#include <timer.h> +#include <bsp.h> + +unsigned get_hz(void) +{ + return bsp_clock_speed(); +} + +unsigned ticks_since_boot(void) +{ + extern unsigned long long _timebase(void); + return (unsigned) (_timebase()); +} + +void sleep_ticks(unsigned ticks) +{ + unsigned then = ticks + ticks_since_boot(); + while(ticks_since_boot() < then) + ; +} + +void udelay(int usecs) +{ + unsigned ticksperusec = get_hz() / 1000000; + + sleep_ticks(ticksperusec * usecs); +} |