rt-thread/bsp/imx6ul/platform/include/mx6ul/plat_startup.h

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_