;!***************************************************************************
;!
;! FILE NAME  : initial_boot.s
;!
;! DESCRIPTION: This piece of code is loaded at bootstrap and is put in the
;!              cache. Depending of how R_BUS_STATUS<2:1> is set different 
;!              kinds of bootstrap is performed.
;!
;!              00 - Normal boot. No bootstrap is performed and this code
;!                   is never loaded.
;!              01 - Serial boot. 784 bytes is loaded and execution starts
;!                   at 0x380000F0.
;!              11 - Paralell boot. 784 bytes is loaded and execution starts
;!                   at 0x380000F0.
;!              10 - Network boot. 1484 bytes is loaded and execution start
;!                   at 0x380000F4.
;!
;!              The purpose of this code is to complete the bootstrap by
;!              loading some flash-programmer into the DRAM.
;!
;!              Must be linked to 0x380000F0  (Cached address)
;!              The order of the modules in the initial_boot code IS
;!              improtant. The serial and parallel code must be linked in
;!              before the network code.
;!
;! ---------------------------------------------------------------------------
;! HISTORY
;!
;! DATE         NAME               CHANGES
;! ----         ----               -------
;! Feb 27 1998  Pontus Soderstrom  Initial version
;! Mar 16 1998  Mikael Starvik     Added setting of DRAM registers
;!                                 Added ram_error
;!                                 Changed parallell port registers
;! Mar 26 1998  Mikael Starvik     Updates after review. Changed CACHE_END,
;!                                 added reg_def.h. Changed LEDs to active low.
;! --------------------------------------------------------------------------
;! (C) Copyright 1998, Axis Communications AB, LUND, SWEDEN
;!***************************************************************************
; %Z% %M% %I% %G%

#define SVINTO_TESTCARD
#undef TESTCARD_4MEG
#define TESTCARD_16MEG
	
;********** INCLUDE FILE SECTION ***********************************

#define ASSEMBLER_MACROS_ONLY
#include <asm/sv_addr_ag.h>
		
;********** CONSTANTS *****************************
#define SER_BOOT_BITNR 1
#define NET_BOOT_BITNR 2

#define DEF_R_WAITSTATES         \
  IO_FIELD(R_WAITSTATES, flash_zw, 2)           |\
  IO_FIELD(R_WAITSTATES, flash_ew, 2)           |\
  IO_FIELD(R_WAITSTATES, flash_lw, 6)		|\
  IO_FIELD(R_WAITSTATES, sram_zw, 2)           |\
  IO_FIELD(R_WAITSTATES, sram_ew, 1)           |\
  IO_FIELD(R_WAITSTATES, sram_lw, 5)

#define DEF_R_BUS_CONFIG         \
  IO_STATE(R_BUS_CONFIG, dma_burst, burst16)    |\
  IO_STATE(R_BUS_CONFIG, flash_bw, bw16)	|\
  IO_STATE(R_BUS_CONFIG, sram_bw, bw32)

#ifdef SVINTO_TESTCARD

#ifdef TESTCARD_4MEG
		;; for Toshiba 321050 32-bit DIMM modules
#define DEF_R_DRAM_CONFIG        \
  IO_STATE(R_DRAM_CONFIG, wmm1, norm)                  |\
  IO_STATE(R_DRAM_CONFIG, wmm0, norm)                  |\
  IO_FIELD(R_DRAM_CONFIG, sh1, 2)                      |\
  IO_FIELD(R_DRAM_CONFIG, sh0, 2)                      |\
  IO_STATE(R_DRAM_CONFIG, w, bw32)                     |\
  IO_STATE(R_DRAM_CONFIG, c, byte)                     |\
  IO_STATE(R_DRAM_CONFIG, e, fast)                      |\
  IO_FIELD(R_DRAM_CONFIG, group_sel, 22)               |\
  IO_FIELD(R_DRAM_CONFIG, ca1, 3)                      |\
  IO_STATE(R_DRAM_CONFIG, bank23sel, bank0)               |\
  IO_FIELD(R_DRAM_CONFIG, ca0, 3)                      |\
  IO_STATE(R_DRAM_CONFIG, bank01sel, bank0)

#define DEF_R_DRAM_TIMING        \
  IO_STATE(R_DRAM_TIMING, ref, e13us)                  |\
  IO_FIELD(R_DRAM_TIMING, rp, 2)                       |\
  IO_FIELD(R_DRAM_TIMING, rs, 1)                       |\
  IO_FIELD(R_DRAM_TIMING, rh, 1)                       |\
  IO_STATE(R_DRAM_TIMING, w, norm)                     |\
  IO_STATE(R_DRAM_TIMING, c, ext)                      |\
  IO_FIELD(R_DRAM_TIMING, cz, 0)                       |\
  IO_FIELD(R_DRAM_TIMING, cp, 0)                       |\
  IO_FIELD(R_DRAM_TIMING, cw, 3)                       

#else /* TESTCARD_16MEG */

#define DEF_R_DRAM_CONFIG \
    IO_STATE( R_DRAM_CONFIG, wmm1,      norm )  | \
    IO_STATE( R_DRAM_CONFIG, wmm0,      norm )  | \
    IO_FIELD( R_DRAM_CONFIG, sh1,       3 )     | \
    IO_FIELD( R_DRAM_CONFIG, sh0,       3 )     | \
    IO_STATE( R_DRAM_CONFIG, w,         bw32 )  | \
    IO_STATE( R_DRAM_CONFIG, c,         byte )  | \
    IO_STATE( R_DRAM_CONFIG, e,         fast )  | \
    IO_FIELD( R_DRAM_CONFIG, group_sel, 24 )    | \
    IO_FIELD( R_DRAM_CONFIG, ca1,       4 )     | \
    IO_STATE( R_DRAM_CONFIG, bank23sel, bank0 ) | \
    IO_FIELD( R_DRAM_CONFIG, ca0,       4 )     | \
    IO_STATE( R_DRAM_CONFIG, bank01sel, bank0 )
	
#define DEF_R_DRAM_TIMING \
    IO_STATE( R_DRAM_TIMING, ref, e13us) | \
    IO_FIELD( R_DRAM_TIMING, rp , 2    ) | \
    IO_FIELD( R_DRAM_TIMING, rs , 1    ) | \
    IO_FIELD( R_DRAM_TIMING, rh , 1    ) | \
    IO_STATE( R_DRAM_TIMING, w  , norm ) | \
    IO_STATE( R_DRAM_TIMING, c  , ext  ) | \
    IO_FIELD( R_DRAM_TIMING, cz , 1    ) | \
    IO_FIELD( R_DRAM_TIMING, cp , 1    ) | \
    IO_FIELD( R_DRAM_TIMING, cw , 3    )
	
#endif
	
#else
	;; for the memory onboard the Stallone boards
#define DEF_R_DRAM_CONFIG        \
  IO_STATE(R_DRAM_CONFIG, wmm1, wmm)                  |\
  IO_STATE(R_DRAM_CONFIG, wmm0, wmm)                  |\
  IO_FIELD(R_DRAM_CONFIG, sh1, 3)                      |\
  IO_FIELD(R_DRAM_CONFIG, sh0, 3)                      |\
  IO_STATE(R_DRAM_CONFIG, w, bw32)                     |\
  IO_STATE(R_DRAM_CONFIG, c, byte)                     |\
  IO_STATE(R_DRAM_CONFIG, e, edo)                      |\
  IO_FIELD(R_DRAM_CONFIG, group_sel, 26)               |\
  IO_FIELD(R_DRAM_CONFIG, ca1, 4)                      |\
  IO_FIELD(R_DRAM_CONFIG, bank23sel, 25)               |\
  IO_FIELD(R_DRAM_CONFIG, ca0, 4)                      |\
  IO_STATE(R_DRAM_CONFIG, bank01sel, bank0)

#define DEF_R_DRAM_TIMING        \
  IO_STATE(R_DRAM_TIMING, ref, e13us)                  |\
  IO_FIELD(R_DRAM_TIMING, rp, 2)                       |\
  IO_FIELD(R_DRAM_TIMING, rs, 1)                       |\
  IO_FIELD(R_DRAM_TIMING, rh, 3)                       |\
  IO_STATE(R_DRAM_TIMING, w, norm)                     |\
  IO_STATE(R_DRAM_TIMING, c, ext)                      |\
  IO_FIELD(R_DRAM_TIMING, cz, 1)                       |\
  IO_FIELD(R_DRAM_TIMING, cp, 0)                       |\
  IO_FIELD(R_DRAM_TIMING, cw, 1)                       

#endif
	
#define DEF_R_PORT_PA_SET        \
  IO_STATE(R_PORT_PA_SET, dir0, input)           |\
  IO_STATE(R_PORT_PA_SET, dir1, input)           |\
  IO_STATE(R_PORT_PA_SET, dir2, output)          |\
  IO_STATE(R_PORT_PA_SET, dir3, output)          |\
  IO_STATE(R_PORT_PA_SET, dir4, output)          |\
  IO_STATE(R_PORT_PA_SET, dir5, output)          |\
  IO_STATE(R_PORT_PA_SET, dir6, input)          |\
  IO_STATE(R_PORT_PA_SET, dir7, output)          |\
  IO_FIELD(R_PORT_PA_SET, data_out, 0)
	
  .data
  .set  CACHE_END, 0x38001eff

;********** VARIABLE DECLARATION SECTION ***************************
 
  .data
  .comm _product_hardware_id,2
	
;********** EXTERNALS **********************************************

  .text
  .globl   start                  ; reset point; required by linker
  .globl   _boot_file_size
  .globl   _product_hardware_id	

;********** PROGRAM SECTION ****************************************

  .text

start:
  nop
  nop
  jump start2

before_header:
_boot_file_size:
        .dword    0xffffffff    ; Size of HWB (will be filled in by mkglow)  
        .word     0             ; HWB header is type 0 
        .dword    0xffffffff    ; File size will be filled in by mkflash  
#if 0
before_magic_number:
        .word     after_magic_number - before_magic_number - 2
        .ascii    MAGIC_NUMBER
after_magic_number:
before_comment:
        .word     after_comment - before_comment - 2
        .ascii    "This is an Etrax Linux boot file! "
#ifndef PRODUCT_ID
#error No PRODUCT_ID defined -- check project.h
#endif
        .ascii    PRODUCT_ID
        .ascii    "V"
        .ascii    PRODUCT_VERSION
#endif
        .ascii    ". Copyright (c) Axis Communications 1998\n\0"
	.align 2
after_comment:
after_header:
		
start2:
;
; Init stack
;
  move.d   CACHE_END, SP ; Place the stack in cache

;
; Memory configuration
;
  move.d   DEF_R_WAITSTATES, r0
  move.d   r0, [R_WAITSTATES]

  move.d   DEF_R_BUS_CONFIG, r0
  move.d   r0, [R_BUS_CONFIG]
  
  move.d   DEF_R_DRAM_CONFIG, r0
  move.d   r0, [R_DRAM_CONFIG]

  move.d   DEF_R_DRAM_TIMING, r0
  move.d   r0, [R_DRAM_TIMING]


;
; General port configuration
;
  move.d   DEF_R_PORT_PA_SET, r0
  move.d   r0, [R_PORT_PA_SET]
			
;  jsr _ser_init			
  nop
;
; Just wait a while to see that it starts.
;
;  move.d   100000000, r0	
;delay_loop:
;  subq     1, r0
;  bne      delay_loop
;  nop

#if 0
        ; clear Ram 
	move.d 0xC0000000,r1
	move.d 0xC2000000,r2
	move.d ram_error,r3
   
	jsr ram_clear		 
        nop
#endif
	        
; Just wait a while to see that it starts.
;
;  move.d   100000000, r0	
;delay_loop2:
;  subq     1, r0
;  bne      delay_loop2
;  nop
   
;
; Call the main program.
;
  jsr _initial_net_boot     ; Never returns 

; Pattern to display if RAM error is detected 
ram_error:	
#ifdef HW_ID_IN_FLASH /* Storage */ 		
   .dword  0x00100000 ; Delay value 
   .dword  0x00000000 ; All LEDs on 
   .dword  0x00100000 ; Delay value 
   .dword  0x0000001C ; All LEDs off 
   .dword  0
#else
   .dword  0x00100000  ; Delay value 
   .dword  0x00000000  ; All LEDs on 
   .dword  0x00100000  ; Delay 
   .dword  0x00000004  ; All LEDs off
   .dword  0
#endif
		
	; DRAM test 
ram_pattern:
   .dword   0xA5A55A5A          ; pattern to use in RAM test
   .dword   0xC33C3CC3
   .dword   0x81812424
   .dword   0x42421818
   .dword   0x01234567
   .dword   0x89ABCDEF
   .dword   0x90022700

#if 0	
;#
;# Test and clear RAM
;#
;# Inpars : r1 = RAM low address
;#          r2 = RAM high address
;#          r3 = Error to display (Flash leds)
;# Changes : r8, r9, r10, r11
;#
ram_test:
; first load inital block with test data
  move.d r1, r9                 ; RAM low
  move.d ram_pattern, r8
  move.d 28, r12                ; pattern size
copy_initial:
  move.d [r8+], r11
  move.d r11, [r9+]
  subq 4, r12                   ; 4 bytes at a time
  bne copy_initial
  nop
; next fill rest of RAM
  move.d r2, r12                ; RAM high
  sub.d  r1, r12                ; minus RAM lo => len
  subq 28, r12                  ; first pattern already loaded
  move.d r1, r8                 ; RAM lo = source address
  move.d r8, r9                 ; destination address
  addq 28, r9                   ; destination is one block up
copy_rest:
  move.d [r8+], r11
  move.d r11, [r9+]
  subq 4, r12                   ; 4 bytes at a time
  bne copy_rest
  nop

; now verify initial block contains test data
  move.d r1, r9                 ; RAM low
  move.d ram_pattern, r8
  move.d 28, r12                ; pattern size

test_initial:
  move.d [r8+], r11
  cmp.d [r9+], r11
  bne ram_bad
  nop
  subq 4, r12                   ; 4 bytes at a time
  bne test_initial
  nop

; now test rest of RAM against first block
  move.d r2, r12                ; RAM high
  sub.d  r1, r12                ; minus RAM lo => len
  subq 28, r12                  ; first pattern already tested
  move.d r1, r8                 ; RAM lo = source address
  move.d r8, r9                 ; address to compare with
  addq 28, r9                   ; it is one block up
test_rest:
  move.d [r8+], r11
  cmp.d [r9+], r11
  bne ram_bad
  nop
  subq 4, r12                   ; 4 bytes at a time
  bne test_rest
  nop
#endif
; RAM is ok. Now clear RAM, and return

ram_clear:	
  move.d 0x0,r6
  move.d r1, r12                ; RAM low
ram_loop:
  move.d r6,[r12]
  addq 4, r12                   ; step up four bytes
  cmp.d r12, r2                 ; reached RAM hi?
  bne ram_loop                  ; no, clear some more
  nop
  ret
  nop
#if 0
ram_bad:
  nop
  move.d r3, r11 ; flash leds appropriately
  ba display_error
  nop

	
		

;#
;# Display error
;#
;# Inparameters: r11    pointer to error table
;#                      each entry is a dword with a delay value,
;#                      followed by a byte with a value to display
;#
;#
display_error:
  move.d r11, r7                ; save error table pointer
next_error_image:
  move.d [r7+], r8              ; counter value
  beq display_error             ; read table from start
  nop
  move.d [r7+], r9              ; value to set (on led port)
  move.b r9, [R_PORT_PA_DATA]   ; set value on LED port
error_timer:                    ; wait specified amount of time
  subq 1, r8
  bne error_timer
  nop
  ba next_error_image
  nop

#endif
; ********************** END OF FILE BOOT_ETR.S ***************************











