summaryrefslogtreecommitdiffstats
path: root/pk/ppe42/ppe42_boot.S
blob: 32fdfd3a074a180c423b806b46244687ed12d483 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2014
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------
        
/// \file ppe42_boot.S
/// \brief PK bootloader for PPE42

        .nolist
#include "pk.h"
        .list
        
### PK Bootloader for PPE42
###
### This is the basic restart initialization of the processor.  
### Parts of this code were derived from examples in the IBM OSopen
### OpenBIOS for the 405GP written by James Burke.
###
### This code does not really do very much, just makes sure that there will
### be a reasonable state in the machine when control is turned over to
### the PK application.  Any core setup that requires SPR access will be done
### here. All other setup is expected to take place in system-specific
### routines. 
###
### From the PowerPC 405-S Embedded Core User's manual:
###
### "In general, the contents of SPRs are undefined after a core, chip or
### system reset. Some SPRs retain the content they had before the reset
### occurred."
###
### Registers fully reset:
###     DBCR1 - Data compares disabled
###     DCWR  - Data cache write-through disabled
###     ESR   - No exception syndromes
###     MSR   - No exceptions/interrupts are allowed
### 
### Registers partially reset:
###     CCR0        = 0x00700000 - Sets ICU and DCU PLB Priority
###     DBCR0 [EDM] = 0          - External debug mode disabled
###           [RST] = 0          - No reset action
###     DBSR  [MRR] = x          - x indicates most recent reset action
###     SGR         = 0xffffffff - Storage is guarded
###     TCR   [WRC] = 0          - Watchdog timer reset disabled
###     TSR   [WRS] = x          - x is a copy of TCR[WRC] Watchdog reset status
###           [PIS] = x          - undefined

        .global_function __pk_boot
        .global __reset_trap
        
__pk_boot:
        
        ## Trap the reset for the debugger.  Set R0 to a non-zero value in the
        ## debugger to continue.

        .if     PPE42_RESET_TRAP
        li      %r0, 0
__reset_trap:   
        cmpwi   %r0, 0          
        beq     __reset_trap
        .endif
        
        ## Set up PowerPC EABI constant registers.  These registers are never
        ## again touched by the PK kernel or the application (if they are
        ## behaving).

        _liw    %r2, _SDA2_BASE_
        _liw    %r13, _SDA_BASE_

        ## Clear the timer control register.  This masks all timer interrupts.

        li      %r3, 0
        mttcr   %r3

        ## The stack pointer is initialized for use by the remainder of the 
        ## initialization, including the application main(). The linker script
        ## defines the initial stack area.
        ## 
        ## Stacks are always 8-byte aligned.  A '0' is stored at the
        ## stack pointer to indicate the end of the stack chain. Stack frames
        ## always consist of at least 8 bytes - the backchain pointer and the
        ## slot above the backchain pointer for the callee's LR.
        
        _liw    %r1, _PK_INITIAL_STACK
        _clrfield %r1, %r1, 3, 29 # 8-byte align
        li      %r3, 0
        stwu    %r3, -8(%r1)
        
        ## SPRG0 (__PkKernelContext) is initialized to 0
        ## indicating that the PK kernel is not in thread mode, and no
        ## interrupts are active.

        li      %r3, 0
        mtsprg0 %r3

        ## Set up the initial value of Debug Control Register 0.  Note that
        ## DBCR1 is specified to be cleared at reset.  VBU simulation requested
        ## an option that this register not be modified so that they could
        ## completely control debug behavior from reset of the PPE42.

#ifndef NO_INIT_DBCR0
        _liwa   %r3, PPE42_DBCR_INITIAL
        mtdbcr  %r3
#endif

        ## The exception vector prefix is set - it must be 512 byte aligned.
        ## NOTE: for PPE42, the IVPR is read only, but can be changed through scoms
        
        #_liw    %r3, __vectors
        #andi.   %r4, %r3, 0x01ff
        #beq     1f
        #_pk_panic PPE42_BOOT_VECTORS_NOT_ALIGNED
#1:      
        #mtivpr  %r3
        #sync

        ## The MSR to be used during the rest of intialization is
        ## established.  This MSR should NOT enable 
        ## interrupts, but could enable machine check exceptions.

        _liwa   %r3, PPE42_MSR_INITIAL
        mtmsr   %r3
        sync

#ifdef PK_BOOT_FROM_ROM

        ## NB:  I don't think the old linker scripts were necessarily the most
        ## optimal.  We need to revisit this if we actually do ROM boots in PK
        ## Version 2. Not sure the comments are correct.

        ## Data is copied from the initial ROM image to the RAM.  The 
        ## address symbols are defined in the linker command file. The linker 
        ## will have zeroed this area in the ROM image.

        liw     %r3, __pk_ram_lma - 4 # src
        liw     %r4, __pk_ram_vma - 4 # dest
        liw     %r5, __pk_ram_size
        liw     %r6, 2
        srw     %r5, %r5, %r6   # Number of word transfers
        mtctr   %r5

copy_loop:
        lwzu    %r5, 4(%r3)
        stwu    %r5, 4(%r4)
        bdnz    copy_loop

#endif /* PK_BOOT_FROM_ROM */
        

        ## Call the system setup code.
        
        bl      __ppe42_system_setup
        
        ## Call the application. If for some reason we return from
        ## the call of the application we call an alternate entry point of the
        ## idle thread.
        ##      
        ## An initial argc/argv can be passed into main(). argc is expected to
        ## be a 32-bit immediate integer, and argv is expected to be a 32-bit
        ## absolute or relocatable expression. 

        _liwa   %r3, PPE42_ARGC_INITIAL
        _liw    %r4, PPE42_ARGV_INITIAL
        bl      __pk_main

        b       __pk_idle_thread_from_bootloader

        .epilogue __pk_boot

OpenPOWER on IntegriCloud