377 lines
11 KiB
C
377 lines
11 KiB
C
/*
|
|
* Copyright (C) 2012, Freescale Semiconductor, Inc. All Rights Reserved
|
|
* THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
|
|
* BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
|
|
* Freescale Semiconductor, Inc.
|
|
*/
|
|
|
|
/*!
|
|
* @file plat_startup.inc
|
|
* @brief This file contains start-up DCD.
|
|
*
|
|
* @ingroup diag_init
|
|
*/
|
|
/* *INDENT-OFF* */
|
|
#ifndef _PLAT_STARTUP_H_
|
|
#define _PLAT_STARTUP_H_
|
|
|
|
#include "soc_memory_map.h"
|
|
#define IMAGE_ENTRY_ADDR 0x80000000
|
|
#define IMAGE_SIZE 4*1024*1024
|
|
|
|
#define L2CC_REG1_CTRL 0x00A02100
|
|
#define L2CC_INV_REG 0x00A0277C
|
|
#define L2CC_TAG_RAM_CTRL 0x00A02108
|
|
#define L2CC_DAT_RAM_CTRL 0x00A0210C
|
|
#define L2CC_PREFETCH_CTRL 0x00A02F60
|
|
|
|
#define ROM_API_TABLE_BASE_ADDR (0x00000180)
|
|
#define ROM_API_HWCNFG_SETUP_OFFSET (0x08)
|
|
|
|
#define PLATFORM_INIT plat_dcd_startup
|
|
|
|
#define ASM_REG32_WR(i, addr, val) \
|
|
ldr r0, =addr; \
|
|
ldr r1, =val; \
|
|
str r1, [r0];
|
|
|
|
// image starts at 0x00907000
|
|
//flash header & DCD @ 0x400
|
|
.macro plat_dcd_startup
|
|
b startup
|
|
.org 0x400
|
|
/* First IVT to copy the plugin that initializes the system into OCRAM */
|
|
ivt_header: .long 0x402000D1 //Tag=0xD1, Len=0x0020, Ver=0x40
|
|
app_code_jump_v: .long 0x00907458 // Plugin entry point, address after the second IVT table
|
|
reserv1: .long 0x0
|
|
dcd_ptr: .long 0x0
|
|
boot_data_ptr: .long 0x00907420
|
|
self_ptr: .long 0x00907400
|
|
app_code_csf: .long 0x0 // reserve 4K for csf
|
|
reserv2: .long 0x0
|
|
boot_data: .long 0x00907000
|
|
image_len: .long 16*1024
|
|
plugin: .long 0x1 // Enable plugin flag
|
|
|
|
/* Second IVT to give entry point into the bootloader copied to DDR */
|
|
ivt2_header: .long 0x402000D1 //Tag=0xD1, Len=0x0020, Ver=0x40
|
|
app2_code_jump_v: .long startup // Entry point for the bootloader
|
|
reserv3: .long 0x0
|
|
dcd2_ptr: .long 0x0
|
|
boot_data2_ptr: .long boot_data2
|
|
self_ptr2: .long ivt2_header
|
|
app_code_csf2: .long 0x0 // reserve 4K for csf
|
|
reserv4: .long 0x0
|
|
boot_data2: .long IMAGE_ENTRY_ADDR
|
|
image_len2: .long IMAGE_SIZE
|
|
plugin2: .long 0x0
|
|
|
|
// Here starts the plugin code
|
|
plugin_start:
|
|
// Save the return address and the function arguments
|
|
push {r0-r4, lr}
|
|
|
|
#if defined(EVB) || defined(SABRE_LITE)
|
|
ASM_REG32_WR(0, 0x020bc000, 0x30)
|
|
|
|
|
|
ASM_REG32_WR(0, 0x020c4068, 0xffffffff)
|
|
ASM_REG32_WR(0, 0x020c406c, 0xffffffff)
|
|
ASM_REG32_WR(0, 0x020c4070, 0xffffffff)
|
|
ASM_REG32_WR(0, 0x020c4074, 0xffffffff)
|
|
ASM_REG32_WR(0, 0x020c4078, 0xffffffff)
|
|
ASM_REG32_WR(0, 0x020c407c, 0xffffffff)
|
|
ASM_REG32_WR(0, 0x020c4080, 0xffffffff)
|
|
ASM_REG32_WR(0, 0x020c4084, 0xffffffff)
|
|
|
|
ASM_REG32_WR(0, 0x020E04B4, 0x000C0000)
|
|
ASM_REG32_WR(0, 0x020E04AC, 0x00000000)
|
|
ASM_REG32_WR(0, 0x020E027C, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0250, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E024C, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0490, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0288, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0270, 0x00000000)
|
|
ASM_REG32_WR(0, 0x020E0260, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0264, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E04A0, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0494, 0x00020000)
|
|
ASM_REG32_WR(0, 0x020E0280, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0284, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E04B0, 0x00020000)
|
|
ASM_REG32_WR(0, 0x020E0498, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E04A4, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0244, 0x00000030)
|
|
ASM_REG32_WR(0, 0x020E0248, 0x00000030)
|
|
ASM_REG32_WR(0, 0x021B001C, 0x00008000)
|
|
ASM_REG32_WR(0, 0x021B0800, 0xA1390003)
|
|
ASM_REG32_WR(0, 0x021B080C, 0x001b001E)
|
|
ASM_REG32_WR(0, 0x021B083C, 0x42400240)
|
|
ASM_REG32_WR(0, 0x021B0848, 0x00003A3E)
|
|
ASM_REG32_WR(0, 0x021B0850, 0x00003230)
|
|
ASM_REG32_WR(0, 0x021B081C, 0x33333333)
|
|
ASM_REG32_WR(0, 0x021B0820, 0x33333333)
|
|
ASM_REG32_WR(0, 0x021B082C, 0xf3333333)
|
|
ASM_REG32_WR(0, 0x021B0830, 0xf3333333)
|
|
ASM_REG32_WR(0, 0x021B08C0, 0x00922012)
|
|
ASM_REG32_WR(0, 0x021B08b8, 0x00000800)
|
|
ASM_REG32_WR(0, 0x021B0004, 0x0002002D)
|
|
ASM_REG32_WR(0, 0x021B0008, 0x1B333000)
|
|
ASM_REG32_WR(0, 0x021B000C, 0x676B54B3)
|
|
ASM_REG32_WR(0, 0x021B0010, 0xB68E0A83)
|
|
ASM_REG32_WR(0, 0x021B0014, 0x01FF00DB)
|
|
ASM_REG32_WR(0, 0x021B0018, 0x00211740)
|
|
ASM_REG32_WR(0, 0x021B001C, 0x00008000)
|
|
ASM_REG32_WR(0, 0x021B002C, 0x000026D2)
|
|
ASM_REG32_WR(0, 0x021B0030, 0x006C1023)
|
|
ASM_REG32_WR(0, 0x021B0040, 0x0000005F)
|
|
ASM_REG32_WR(0, 0x021B0000, 0x85180000)
|
|
ASM_REG32_WR(0, 0x021B001C, 0x02008032)
|
|
ASM_REG32_WR(0, 0x021B001C, 0x00008033)
|
|
ASM_REG32_WR(0, 0x021B001C, 0x00048031)
|
|
ASM_REG32_WR(0, 0x021B001C, 0x15208030)
|
|
ASM_REG32_WR(0, 0x021B001C, 0x04008040)
|
|
ASM_REG32_WR(0, 0x021B0020, 0x00000800)
|
|
ASM_REG32_WR(0, 0x021B0818, 0x00000227)
|
|
ASM_REG32_WR(0, 0x021B0004, 0x0002552D)
|
|
ASM_REG32_WR(0, 0x021B0404, 0x00011006)
|
|
ASM_REG32_WR(0, 0x021B001C, 0x00000000)
|
|
|
|
|
|
#else
|
|
#error "Please add the DDR initialization code for this board, unless you can make sure the existing code can be shared."
|
|
#endif
|
|
|
|
read_obds:
|
|
/********************
|
|
The following is to fill in those arguments for this ROM function
|
|
pu_irom_hwcnfg_setup(void **start, size_t *bytes, const void *boot_data)
|
|
|
|
This function is used to copy data from the storage media into DDR.
|
|
|
|
start - Initial (possibly partial) image load address on entry. Final image load address on exit.
|
|
bytes - Initial (possibly partial) image size on entry. Final image size on exit.
|
|
boot_data - Initial @ref ivt Boot Data load address.
|
|
*/
|
|
|
|
adr r0, DDR_DEST_ADDR
|
|
adr r1, COPY_SIZE
|
|
adr r2, BOOT_DATA
|
|
|
|
/*
|
|
* check the _pu_irom_api_table for the address
|
|
*/
|
|
before_calling_rom___pu_irom_hwcnfg_setup:
|
|
//mov r4, #0x2000
|
|
//add r4, r4, #0xed
|
|
//blx r4 // This address might change in future ROM versions.
|
|
ldr r3, =ROM_API_TABLE_BASE_ADDR /* Address of rom_api_table is 0xc0 */
|
|
ldr r4, [r3, #ROM_API_HWCNFG_SETUP_OFFSET] /* hwcnfg setup function address is 3rd entry in the api table address 0xc8 */
|
|
blx r4 /* call into ROM function */
|
|
after_calling_rom___pu_irom_hwcnfg_setup:
|
|
|
|
/* SDRAM has been setup, binary image has been copied to SDRAM */
|
|
b startup // Jump to our code directly
|
|
|
|
DDR_DEST_ADDR: .word IMAGE_ENTRY_ADDR
|
|
COPY_SIZE: .word IMAGE_SIZE
|
|
BOOT_DATA: .word IMAGE_ENTRY_ADDR
|
|
.word IMAGE_SIZE //real data to be copied by the pu_irom_hwcnfg_setup()
|
|
.word 0
|
|
|
|
.endm //plat_dcd_startup
|
|
|
|
// #define PLATFORM_ASM_STARTUP platform_asm_startup
|
|
.macro platform_asm_startup
|
|
|
|
config_L2_cache:
|
|
disable_L2_cache
|
|
|
|
init_aips_start:
|
|
init_aips
|
|
|
|
init_reloc_start:
|
|
/* Check if need to copy image to Redboot ROM space */
|
|
ldr r0, =0xFFFFF000
|
|
and r0, r0, pc
|
|
ldr r1, =IMAGE_ENTRY_ADDR
|
|
cmp r0, r1
|
|
beq skip_SDRAM_copy
|
|
|
|
add r2, r0, #IMAGE_SIZE
|
|
|
|
1: ldmia r0!, {r3-r10}
|
|
stmia r1!, {r3-r10}
|
|
cmp r0, r2
|
|
ble 1b
|
|
/* Jump to SDRAM */
|
|
ldr r1, =0xFFFF
|
|
and r0, pc, r1 /* offset of pc */
|
|
ldr r1, =(IMAGE_ENTRY_ADDR + 0x8)
|
|
add pc, r0, r1
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
skip_SDRAM_copy:
|
|
.endm //platform_asm_startup
|
|
|
|
/* AIPS setup - Only setup MPROTx registers. The PACR default values are good.*/
|
|
.macro init_aips
|
|
/*
|
|
* Set all MPROTx to be non-bufferable, trusted for R/W,
|
|
* not forced to user-mode.
|
|
*/
|
|
ldr r0, =AIPS_TZ1_BASE_ADDR
|
|
ldr r1, =0x77777777
|
|
str r1, [r0, #0x00]
|
|
str r1, [r0, #0x04]
|
|
|
|
ldr r0, =AIPS_TZ2_BASE_ADDR
|
|
str r1, [r0, #0x00]
|
|
str r1, [r0, #0x04]
|
|
|
|
.endm /* init_aips */
|
|
|
|
.macro clean_L1_DCache
|
|
mov r0, #0
|
|
mcr p15, 2, r0, c0, c0, 0 // select DCache
|
|
mrc p15, 1, r0, c0, c0, 0 // read CCSIDR
|
|
mov r0, r0, ASR #13
|
|
ldr r3, =0x3FFF
|
|
and r0, r0, r3
|
|
cmp r0, #0x7F
|
|
moveq r6, #0x1000 // 4KB * 4way = 16KB
|
|
beq clean_and_invalidate_L1_dcache
|
|
cmp r0, #0xFF
|
|
moveq r6, #0x2000 // 32KB
|
|
beq clean_and_invalidate_L1_dcache
|
|
movne r6, #0x4000 // 64KB
|
|
|
|
clean_and_invalidate_L1_dcache:
|
|
mov r2, #0x00000000
|
|
mov r3, #0x40000000
|
|
mov r4, #0x80000000
|
|
mov r5, #0xC0000000
|
|
|
|
clean_and_invalidate_L1_dcache_byset:
|
|
mcr p15, 0, r2, c7, c14, 2 //clean and invalidate dcache on way 0
|
|
mcr p15, 0, r3, c7, c14, 2 //clean and invalidate dcache on way 1
|
|
mcr p15, 0, r4, c7, c14, 2 //clean and invalidate dcache on way 2
|
|
mcr p15, 0, r5, c7, c14, 2 //clean and invalidate dcache on way 3
|
|
add r2, r2, #0x20
|
|
add r3, r3, #0x20
|
|
add r4, r4, #0x20
|
|
add r5, r5, #0x20
|
|
|
|
cmp r2, r6
|
|
bne clean_and_invalidate_L1_dcache_byset
|
|
|
|
.endm
|
|
|
|
.macro enable_L1_cache
|
|
mov r0, #0
|
|
mcr p15, 0, r0, c7, c5, 6 // invalidate BTAC
|
|
mcr p15, 0, r0, c7, c5, 0 // invalidate icache
|
|
|
|
mov r0, #0
|
|
mcr p15, 2, r0, c0, c0, 0 // select DCache
|
|
mrc p15, 1, r0, c0, c0, 0 // read CCSIDR
|
|
mov r0, r0, ASR #13
|
|
ldr r3, =0x3FFF
|
|
and r0, r0, r3
|
|
cmp r0, #0x7F
|
|
moveq r6, #0x1000 // 4KB * 4way = 16KB
|
|
beq invalidate_dcache
|
|
cmp r0, #0xFF
|
|
moveq r6, #0x2000 // 32KB
|
|
beq invalidate_dcache
|
|
movne r6, #0x4000 // 64KB
|
|
|
|
invalidate_dcache:
|
|
mov r2, #0x00000000
|
|
mov r3, #0x40000000
|
|
mov r4, #0x80000000
|
|
mov r5, #0xC0000000
|
|
|
|
invalidate_dcache_byset:
|
|
mcr p15, 0, r2, c7, c6, 2 //invalidate dcache on way 0
|
|
mcr p15, 0, r3, c7, c6, 2 //invalidate dcache on way 1
|
|
mcr p15, 0, r4, c7, c6, 2 //invalidate dcache on way 2
|
|
mcr p15, 0, r5, c7, c6, 2 //invalidate dcache on way 3
|
|
add r2, r2, #0x20
|
|
add r3, r3, #0x20
|
|
add r4, r4, #0x20
|
|
add r5, r5, #0x20
|
|
|
|
cmp r2, r6
|
|
bne invalidate_dcache_byset
|
|
|
|
ldr r0, =0x00930000 //where to store the TLB page table
|
|
mcr p15, 0, r0, c2, c0, 0
|
|
ldr r0, =0x55555555
|
|
mcr p15, 0, r0, c3, c0, 0
|
|
|
|
mrc p15, 0, r0, c1, c0, 0 // read CP15 register 1 into r0
|
|
orr r0, r0, #(0x1<<12) // enable I Cache
|
|
orr r0, r0, #(0x1<<11) // turn on BP
|
|
orr r0, r0, #(0x1<<2) // enable D Cache
|
|
/*Attention: If you want to enable MMU, must set up the TLB tables first!!*/
|
|
bic r0, r0, #(0x1<<0) // disable MMU
|
|
mcr p15, 0, r0, c1, c0, 0 // write CP15 register 1
|
|
.endm
|
|
|
|
.macro disable_L1_cache
|
|
mrc p15, 0, r0, c1, c0, 0
|
|
bic r0, r0, #(0x1<<12)
|
|
bic r0, r0, #(0x1<<11)
|
|
bic r0, r0, #(0x1<<2)
|
|
bic r0, r0, #(0x1<<0)
|
|
mcr p15, 0, r0, c1, c0, 0
|
|
.endm
|
|
|
|
.macro disable_L1_DCache
|
|
mrc p15, 0, r0, c1, c0, 0
|
|
ands r0, r0, #(0x1<<11) //check if L1 DCache has been disabled
|
|
beq disable_L1_DCache_done
|
|
bic r0, r0, #(0x1<<11)
|
|
bic r0, r0, #(0x1<<0) //disable MMU
|
|
mcr p15, 0, r0, c1, c0, 0
|
|
clean_L1_DCache
|
|
disable_L1_DCache_done:
|
|
.endm
|
|
|
|
.macro enable_L2_cache
|
|
/* set latency: 4x cycles read, 2x cycles write, (3x cycles setup)*/
|
|
ldr r1,= L2CC_TAG_RAM_CTRL
|
|
ldr r0,=0x0132
|
|
str r0,[r1]
|
|
ldr r1, =L2CC_DAT_RAM_CTRL
|
|
ldr r0,=0x0132
|
|
str r0,[r1]
|
|
|
|
/* invalidate L2Cache by way */
|
|
ldr r1, =L2CC_INV_REG
|
|
ldr r0, =0xffff
|
|
str r0,[r1]
|
|
l2cc_inv_done:
|
|
ldr r2,[r1]
|
|
mov r0,#0x0
|
|
cmp r2,r0
|
|
bne l2cc_inv_done
|
|
|
|
/* turn on l2 cache */
|
|
ldr r1, =L2CC_REG1_CTRL
|
|
mov r0,#1
|
|
str r0,[r1]
|
|
.endm
|
|
|
|
.macro disable_L2_cache
|
|
ldr r1, =L2CC_REG1_CTRL
|
|
mov r0,#0
|
|
str r0,[r1]
|
|
.endm
|
|
|
|
#endif //_PLAT_STARTUP_H_
|