view src/cs/system/main/gcc/bootentry.S @ 49:4e178a0e90f6

LICENSE added
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 18 Oct 2020 03:39:10 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/*
 * This assembly module is our counterpart to TI's int.s: all boot entry
 * point code that needs to be at the beginning of the flash resides here.
 */

#include "asm_defs.h"
#include "fc-target.h"
#include "rf.cfg"

#if defined(FLASH) && !defined(CONFIG_TARGET_COMPAL)
/*
 * Put something sensible in the boot ROM overlay area, just for the
 * heck of it, or for extra robustness.
 */
	.section	bootrom.overlay,"ax",%progbits
	.code	32
	.org	0
	b	BootROM_disabled_entry
#include "vectors.S"
BootROM_disabled_entry:
/* copy the boot ROM switch code to IRAM and jump to it */
	ldr	r4, =__romswitch_flash_addr
	ldr	r5, =__romswitch_ram_addr
	ldr	r2, =__romswitch_size
1:	ldr	r0, [r4], #4
	str	r0, [r5], #4
	subs	r2, r2, #4
	bhi	1b
	ldr	pc, =__romswitch_ram_addr

	.section	bootrom.switch,"ax",%progbits
	.code	32
	.org	0
@ enable the Calypso boot ROM
	ldr	r1, =0xFFFFFB10
	mov	r2, #0x0100
	strh	r2, [r1]
@ jump to it!
	mov	pc, #0
#endif

	.section	.inttext,"ax",%progbits
	.code	32

#ifdef FLASH
	.org	0
#ifndef CONFIG_TARGET_COMPAL
/* sane targets with Calypso boot ROM enabled by the PCB wiring */
/* provide the necessary magic words for the boot ROM */
	.word	0
	.word	_Firmware_boot_entry
#elif defined(CONFIG_TARGET_C11X) || defined(CONFIG_TARGET_C139) || \
	defined(CONFIG_TARGET_J100)
/*
 * On this target we'll put a patched version of Compal's boot code in
 * flash sector 0 (the brickable one); the main fw images will then be
 * flashed starting at 0x10000, which is where our modified boot code
 * expects them to be.  The interface between our hacked boot code and
 * the main fw has been made to mimic TI's TCS211 reference fw.
 */
#include "vectors.S"
	.org	0x58	/* entry point at 0x10058 */
	b	_Firmware_boot_entry
#elif defined(CONFIG_TARGET_C155)
/*
 * On this target the hand-off point between the bootloader and the main
 * fw image coincides with a flash erase block boundary, thus we can reuse
 * the original bootloader without having to reflash the brickable sector
 * at all.  The following bits will appear at 0x20000.
 */
	.asciz	"FreeCalypso firmware for C155/156 target"
	.org	0xE0
/* C155/156 bootloader jumps here */
	b	_Firmware_boot_entry
#include "vectors.S"
#else
#error "Unsupported flash boot configuration"
#endif
#endif

/* definitions from TI's int.s */

#define	IRQ_STACK_SIZE	128
#define	FIQ_STACK_SIZE	512
#define	SYSTEM_SIZE	1024
#define	TIMER_SIZE	1024
#define	TIMER_PRIORITY	2

@ TI's literal pool before the entry point

addrCS0:           .word   0xfffffb00	@ CS0 address space

EX_MPU_CONF_REG:   .word   0xFFFEF006   @ Extended MPU configuration register address
EX_FLASH_VALUE:    .short  0x0008       @ set bit to enable A22

		   .balign 4

CNTL_ARM_CLK_REG:  .word   0xFFFFFD00   @ CNTL_ARM_CLK register address
DPLL_CNTRL_REG:    .word   0xFFFF9800   @ DPLL control register address
EXTRA_CONTROL_REG: .word   0xFFFFFB10   @ Extra Control register CONF address
MPU_CTL_REG:       .word   0xFFFFFF08   @ MPU_CTL register address

CNTL_ARM_CLK_RST:  .short  0x1081       @ Initialization of CNTL_ARM_CLK register
                                        @ Use DPLL, Divide by 1
DPLL_CONTROL_RST:  .short  0x2002       @ Configure DPLL in default state
DISABLE_DU_MASK:   .short  0x0800       @ Mask to Disable the DU module
ENABLE_DU_MASK:    .short  0xF7FF       @ Mask to Enable the DU module
MPU_CTL_RST:       .short  0x0000       @ Reset value of MPU_CTL register - All protections disabled

@ FreeCalypso change, please see MEMIF-wait-states document
@ in the freecalypso-docs repository for the explanation.

#if (RF_FAM == 12)
CS0_MEM_REG:   .short  0x2a2  @ 1 Dummy Cycle 16 bit 2 WS SW BP enable
CS1_MEM_REG:   .short  0x2a2  @ 1 Dummy Cycle 16 bit 2 WS SW BP enable
CS2_MEM_REG:   .short  0x2a2  @ 1 Dummy Cycle 16 bit 2 WS SW BP enable
#else
CS0_MEM_REG:   .short  0x2a1  @ 1 Dummy Cycle 16 bit 1 WS SW BP enable
CS1_MEM_REG:   .short  0x2a1  @ 1 Dummy Cycle 16 bit 1 WS SW BP enable
CS2_MEM_REG:   .short  0x2a1  @ 1 Dummy Cycle 16 bit 1 WS SW BP enable
#endif
CS3_MEM_REG:   .short  0x283  @ 1 Dummy Cycle  8 bit 3 WS SW BP enable
CS4_MEM_REG:   .short  0xe85  @ default reset value
CS6_MEM_REG:   .short  0x2c0  @ Internal RAM   init : 0 WS, 32 bits, little, write enable
CS7_MEM_REG:   .short  0x040  @ Internal BOOT ROM   init : 0 WS, 32 bits, little, write disable
CTL_MEM_REG:   .short  0x02a  @ rhea strobe 0/1 + API access size adaptation

		.balign	4

	.globl	_Firmware_boot_entry
_Firmware_boot_entry:
@  TI's code from int.s follows

@
@  Configure DPLL register with reset value
@
       ldr     r1,DPLL_CNTRL_REG     @ Load address of DPLL register in R1
       ldrh    r2,DPLL_CONTROL_RST   @ Load DPLL reset value in R2
       strh    r2,[r1]               @ Store DPLL reset value in DPLL register

@
@  Wait that DPLL goes in BYPASS mode
@
Wait_DPLL_Bypass:
       ldr     r2,[r1]               @ Load DPLL register
       and     r2,r2,#1              @ Perform a mask on bit 0
       cmp     r2,#1                 @ Compare DPLL lock bit
       beq     Wait_DPLL_Bypass      @ Wait Bypass mode (i.e. bit[0]='0')

@
@  Configure CNTL_ARM_CLK register with reset value: DPLL is used to
@  generate ARM clock with division factor of 1.
@
       ldr     r1,CNTL_ARM_CLK_REG  @ Load address of CNTL_ARM_CLK register in R1
       ldrh    r2,CNTL_ARM_CLK_RST  @ Load CNTL_ARM_CLK reset value in R2
       strh    r2,[r1]              @ Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register

@
@  Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0'
@
       ldr     r1,EXTRA_CONTROL_REG @ Load address of Extra Control register CONF
       ldrh    r2,ENABLE_DU_MASK    @ Load mask to write in Extra Control register CONF
       ldrh    r0,[r1]              @ Load Extra Control register CONF in r0
       and     r0,r0,r2             @ Enable DU module
       strh    r0,[r1]              @ Store configuration in Extra Control register CONF

@
@  Disable all MPU protections
@
       ldr     r1,MPU_CTL_REG       @ Load address of MPU_CTL register
       ldrh    r2,MPU_CTL_RST       @ Load reset value of MPU_CTL register
       strh    r2,[r1]              @ Store reset value of MPU_CTL register

@ MEMIF timing setup

       ldr     r1,addrCS0
       ldrh    r2,CS0_MEM_REG		    @ ROM initialization
       strh    r2,[r1]                      @ CS0

       ldrh    r2,CS1_MEM_REG               @ RAM Initialization
       strh    r2,[r1,#2]	            @ CS1

       ldrh    r2,CS2_MEM_REG               @ RAM Initialization
       strh    r2,[r1,#4]	            @ CS2

       ldrh    r2,CS3_MEM_REG               @ Parallel I/O on B-Sample
       strh    r2,[r1,#6]                   @ CS3 (unused on EVA4?)

       ldrh    r2,CS4_MEM_REG               @ Latch on B-Sample
       strh    r2,[r1,#0xa]                 @ CS4 (unused on EVA4)

       ldrh    r2,CS6_MEM_REG               @ Internal SRAM initialization
       strh    r2,[r1,#0xc]	            @ CS6 Internal RAM
  
       ldrh    r2,CS7_MEM_REG               @ Internal SRAM initialization
       strh    r2,[r1,#0x8]	            @ CS7 Internal Boot ROM

       ldrh    r2,CTL_MEM_REG               @ API-RHEA configuration
       strh    r2,[r1,#0xe]

@ enable ADD22

       ldr     r1,EX_MPU_CONF_REG
       ldrh    r2,[r1]
       ldr     r0,EX_FLASH_VALUE
       orr     r0, r0, r2
       strh    r0,[r1]

/* Ensure that the processor is in supervisor mode.  */

        MRS     a1,CPSR                     @ Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            @ Clear the mode bits
        ORR     a1,a1,#SUP_MODE             @ Set the supervisor mode bits
        ORR     a1,a1,#LOCKOUT              @ Ensure IRQ and FIQ interrupts are
                                            @   locked out
        MSR     CPSR,a1                     @ Setup the new CPSR

/*
 * FreeCalypso Selenite: if this is a flash build,
 * copy IRAM code and .data from flash to RAM.
 */

#ifdef FLASH
/* copy iram.text to where it's supposed to be */
	ldr	r8, =__iramtext_flash_addr
	ldr	r9, =__iramtext_ram_addr
	ldr	r10, =__iramtext_size
1:	ldmia	r8!, {r0-r7}
	stmia	r9!, {r0-r7}
	subs	r10, r10, #0x20
	bhi	1b
/* likewise copy .data from flash to XRAM */
	ldr	r8, =__initdata_flash_addr
	ldr	r9, =__initdata_ram_addr
	ldr	r10, =__initdata_size
1:	ldmia	r8!, {r0-r7}
	stmia	r9!, {r0-r7}
	subs	r10, r10, #0x20
	bhi	1b
#endif

/* Both flash and XRAM builds: zero .bss */

	ldr	r0, =__intbss_start
	ldr	r1, =__intbss_size
	bl	bzero
	ldr	r0, =__extbss_start
	ldr	r1, =__extbss_size
	bl	bzero

@ TI's int.s code continues

@
@    Initialize the system stack pointers.  This is done after the BSS is
@    cleared because the TCD_System_Stack pointer is a BSS variable!  It is
@    assumed that the .cmd file is written to direct where these stacks should
@    be allocated and to align them on double word boundaries.
@
        LDR     a1,StackSegment             @ Pickup the begining address from .cmd file
                                            @   (is aligned on 8 byte boundary)
        MOV     a2,#SYSTEM_SIZE             @ Pickup system stack size
        SUB     a2,a2,#4                    @ Subtract one word for first addr
        ADD     a3,a1,a2                    @ Build start of system stack area
        MOV     v7,a1                       @ Setup initial stack limit
        LDR     a4,System_Limit             @ Pickup system stack limit address
        STR     v7,[a4, #0]                 @ Save stack limit
        MOV     sp,a3                       @ Setup initial stack pointer
        LDR     a4,System_Stack             @ Pickup system stack address
        STR     sp,[a4, #0]                 @ Save stack pointer
        MOV     a2,#IRQ_STACK_SIZE          @ Pickup IRQ stack size in bytes
        ADD     a3,a3,a2                    @ Allocate IRQ stack area
        MRS     a1,CPSR                     @ Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            @ Clear the mode bits
        ORR     a1,a1,#IRQ_MODE             @ Set the IRQ mode bits
        MSR     CPSR,a1                     @ Move to IRQ mode
        MOV     sp,a3                       @ Setup IRQ stack pointer
        MOV     a2,#FIQ_STACK_SIZE          @ Pickup FIQ stack size in bytes
        ADD     a3,a3,a2                    @ Allocate FIQ stack area
        MRS     a1,CPSR                     @ Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            @ Clear the mode bits
        ORR     a1,a1,#FIQ_MODE             @ Set the FIQ mode bits
        MSR     CPSR,a1                     @ Move to the FIQ mode
        MOV     sp,a3                       @ Setup FIQ stack pointer

        MRS     a1,CPSR                     @ Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            @ Clear the mode bits
        ORR     a1,a1,#ABORT_MODE           @ Set the Abort mode bits
        MSR     CPSR,a1                     @ Move to the Abort mode
        LDR     sp,Exception_Stack          @ Setup Abort stack pointer

        MRS     a1,CPSR                     @ Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            @ Clear the mode bits
        ORR     a1,a1,#UNDEF_MODE           @ Set the Undefined mode bits
        MSR     CPSR,a1                     @ Move to the Undefined mode
        LDR     sp,Exception_Stack          @ Setup Undefined stack pointer
                                            @   (should never be used)

@ go to Supervisor Mode
        MRS     a1,CPSR                     @ Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            @ Clear mode bits
        ORR     a1,a1,#SUP_MODE             @ Set the supervisor mode bits
        MSR     CPSR,a1                     @ All interrupt stacks are setup,
                                            @   return to supervisor mode
@
@    /* Define the global data structures that need to be initialized by this
@       routine.  These structures are used to define the system timer 
@       management HISR.  */
@    TMD_HISR_Stack_Ptr =        (VOID *) a3;
@    TMD_HISR_Stack_Size =       TIMER_SIZE;
@    TMD_HISR_Priority =         TIMER_PRIORITY;
@
@ TMD_HISR_Stack_Ptr points at the top (the lowest address) of the allocated
@ area. The Timer HISR (called "SYSTEM H") and its related stack will be created
@ in TMI_Initialize(). The current stack pointer will be set at the bottom (the
@ lowest address) of the expected area.

        LDR     a4,HISR_Stack_Ptr           @ Pickup variable's address
        ADD     a3,a3,#4                    @ Increment to next available word
        STR     a3,[a4, #0]                 @ Setup timer HISR stack pointer
        MOV     a2,#TIMER_SIZE              @ Pickup the timer HISR stack size
        BIC     a2,a2,#3                    @ Insure word alignment
        ADD     a3,a3,a2                    @ Allocate the timer HISR stack 
                                            @   from available memory
        LDR     a4,HISR_Stack_Size    	    @ Pickup variable's address
        STR     a2,[a4, #0]                 @ Setup timer HISR stack size
        MOV     a2,#TIMER_PRIORITY          @ Pickup timer HISR priority (0-2)
        LDR     a4,HISR_Priority            @ Pickup variable's address
        STR     a2,[a4, #0]                 @ Setup timer HISR priority

/* TI's original code called f_load_int_mem() at this point */
/* let's do our internal ROM enable step here */

	ldr	r1, EXTRA_CONTROL_REG
	ldrh	r0, [r1, #0]
	bic	r0, #0x0300
	orr	r0, #0x0100
	strh	r0, [r1, #0]

@ We now fill up the System, IRQ, FIQ and System Timer HISR stacks with 0xFE for
@ checking the status of the stacks later. 
@ inputs:
@     a3 still has the bottom of all four stacks and is aligned. 
@ algorithm:
@     We start from the top of all four stacks (*System_Limit), which is
@     necessarily aligned.  We store 0xFEFEFEFE until we have filled the
@     bottom of the fourth stack
@ outputs:
@     memory has 0xFE on all four stacks: System, FIQ, IRQ and System Timer HISR
@     a3 still has the bottom of all four stacks

        LDR     a2,System_Limit             @ pickup system stack limit address
        LDR     a1,[a2]                     @ a1 = StackSegment
        LDR     a4,=0xFEFEFEFE

fill_stack:
        STR     a4,[a1],#4                  @ store a word and increment by four
        CMP     a1,a3                       @ is this the last address?
        BLT     fill_stack                  @ if not, loop back

@
@     /* Call INC_Initialize with a pointer to the first available memory 
@        address after the compiler's global data.  This memory may be used
@        by the application.  */
@     INC_Initialize(first_available_memory);
@
	MOV     a1,a3                       @ Pass the first available memory
	B       INC_Initialize              @ to high-level initialization

@ literal pool from int.s (after the code)

StackSegment:
	.word	_Stack_segment_start

System_Limit:
	.word	TCT_System_Limit

System_Stack:
	.word	TCD_System_Stack

HISR_Stack_Ptr:
	.word	TMD_HISR_Stack_Ptr

HISR_Stack_Size:
	.word	TMD_HISR_Stack_Size

HISR_Priority:
	.word	TMD_HISR_Priority

Exception_Stack:
	.word	_Except_Stack_SP