Blame view

kernel/linux-rt-4.4.41/arch/cris/boot/rescue/kimagerescue.S 3.42 KB
5113f6f70   김현기   kernel add
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
  /*
   * Rescue code to be prepended on a kimage and copied to the
   * rescue serial port.
   * This is called from the rescue code, it will copy received data to
   * 4004000 and after a timeout jump to it.
   */
  
  #define ASSEMBLER_MACROS_ONLY
  #include <arch/sv_addr_ag.h>
  
  #define CODE_START 0x40004000
  #define CODE_LENGTH 784
  #define TIMEOUT_VALUE 1000
  
  
  #ifdef CONFIG_ETRAX_RESCUE_SER0
  #define SERXOFF R_SERIAL0_XOFF
  #define SERBAUD R_SERIAL0_BAUD
  #define SERRECC R_SERIAL0_REC_CTRL
  #define SERRDAT R_SERIAL0_REC_DATA
  #define SERSTAT R_SERIAL0_STATUS
  #endif
  #ifdef CONFIG_ETRAX_RESCUE_SER1
  #define SERXOFF R_SERIAL1_XOFF
  #define SERBAUD R_SERIAL1_BAUD
  #define SERRECC R_SERIAL1_REC_CTRL
  #define SERRDAT R_SERIAL1_REC_DATA
  #define SERSTAT R_SERIAL1_STATUS
  #endif
  #ifdef CONFIG_ETRAX_RESCUE_SER2
  #define SERXOFF R_SERIAL2_XOFF
  #define SERBAUD R_SERIAL2_BAUD
  #define SERRECC R_SERIAL2_REC_CTRL
  #define SERRDAT R_SERIAL2_REC_DATA
  #define SERSTAT R_SERIAL2_STATUS
  #endif
  #ifdef CONFIG_ETRAX_RESCUE_SER3
  #define SERXOFF R_SERIAL3_XOFF
  #define SERBAUD R_SERIAL3_BAUD
  #define SERRECC R_SERIAL3_REC_CTRL
  #define SERRDAT R_SERIAL3_REC_DATA
  #define SERSTAT R_SERIAL3_STATUS
  #endif
  
  	.text
  	;; This is the entry point of the rescue code
  	;; 0x80000000 if loaded in flash (as it should be)
  	;; since etrax actually starts at address 2 when booting from flash, we
  	;; put a nop (2 bytes) here first so we dont accidentally skip the di
  
  	nop
  	di
  	;; setup port PA and PB default initial directions and data
  	;; (so we can flash LEDs, and so that DTR and others are set)
  
  	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DIR, $r0
  	move.b	$r0, [R_PORT_PA_DIR]
  	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r0
  	move.b	$r0, [R_PORT_PA_DATA]
  
  	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DIR, $r0
  	move.b	$r0, [R_PORT_PB_DIR]
  	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r0
  	move.b	$r0, [R_PORT_PB_DATA]
  
  	;; We need to setup the bus registers before we start using the DRAM
  #include "../../lib/dram_init.S"
  
  	;; Setup the stack to a suitably high address.
  	;; We assume 8 MB is the minimum DRAM in an eLinux
  	;; product and put the sp at the top for now.
  
  	move.d	0x40800000, $sp
  
  	;; setup the serial port at 115200 baud
  
  	moveq	0, $r0
  	move.d	$r0, [SERXOFF]
  
  	move.b	0x99, $r0
  	move.b	$r0, [SERBAUD]		; 115.2kbaud for both transmit
  					; and receive
  
  	move.b	0x40, $r0		; rec enable
  	move.b	$r0, [SERRECC]
  
  
  	moveq	0, $r1			; "timer" to clock out a LED red flash
  	move.d	CODE_START, $r3		; destination counter
  	move.d	CODE_LENGTH, $r4	; length
  	move.d	TIMEOUT_VALUE, $r5	; "timeout" until jump
  
  wait_ser:
  	addq	1, $r1
  	subq	1, $r5			; decrease timeout
  	beq	jump_start		; timed out
  	nop
  #ifndef CONFIG_ETRAX_NO_LEDS
  #ifdef CONFIG_ETRAX_PA_LEDS
  	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r2
  #endif
  #ifdef CONFIG_ETRAX_PB_LEDS
  	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r2
  #endif
  	move.d	(1 << CONFIG_ETRAX_LED1R) | (1 << CONFIG_ETRAX_LED2R), $r0
  	btstq	16, $r1
  	bpl	1f
  	nop
  	or.d	$r0, $r2		; set bit
  	ba	2f
  	nop
  1:	not	$r0			; clear bit
  	and.d	$r0, $r2
  2:
  #ifdef CONFIG_ETRAX_PA_LEDS
  	move.b	$r2, [R_PORT_PA_DATA]
  #endif
  #ifdef CONFIG_ETRAX_PB_LEDS
  	move.b	$r2, [R_PORT_PB_DATA]
  #endif
  #endif
  
  	;; check if we got something on the serial port
  
  	move.b	[SERSTAT], $r0
  	btstq	0, $r0			; data_avail
  	bpl	wait_ser
  	nop
  
  	;; got something - copy the byte and loop
  
  	move.b	[SERRDAT], $r0
  	move.b	$r0, [$r3+]
  	move.d	TIMEOUT_VALUE, $r5	; reset "timeout"
  	subq	1, $r4			; decrease length
  	bne	wait_ser
  	nop
  jump_start:
  	;; jump into downloaded code
  
  	jump	CODE_START