summaryrefslogtreecommitdiff
path: root/src/arch/ppc/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/ppc/lib')
-rw-r--r--src/arch/ppc/lib/c_start.S109
-rw-r--r--src/arch/ppc/lib/floats.S45
-rw-r--r--src/arch/ppc/lib/floats.inc43
-rw-r--r--src/arch/ppc/lib/setup.c130
-rw-r--r--src/arch/ppc/lib/timebase.S13
-rw-r--r--src/arch/ppc/lib/timer.c31
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);
+}