| /* |
| * 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 |