summaryrefslogtreecommitdiffstats
path: root/arch/cris/boot/rescue/kimagerescue.S
blob: 655b511fecf37ff3e9ada767f8a8b06ba488377b (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
/*
 * 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