您的位置:首页 > 其它

TQ210 —— s5pv210 start.S分析

2016-09-16 09:39 239 查看
/*
*  armboot - Startup Code for S5PC110/ARM-Cortex CPU-core
*
*  Copyright (c) 2009	Samsung Electronics
*
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Base codes by scsuh (sc.suh)
*/
/*
*  mod by lhh
*
*  Our U-Boot Memory Map with static mmu_table
*                                      (offset)
*       --------------------------
*       |     Stack     (512KB)  |
*       --------------------------
*       |     Heap       (1MB+envsize)   |
*       --------------------------
*       |     IRQ Stack  (KB)   | <------------------------ if exists
*       --------------------------
*       |     FIQ Stack  (KB)   | <------------------------ if exists
*       --------------------------
*       |     GBL       (B)   |
*       --------------------------     0x03exxxxx
*       |     BSS and Reserved   |
*       --------------------------     0x03e60000
*       |     U-Boot    (512KB)  |
*       --------------------------     0x03e00000
*/
#include <config.h>
#include <version.h>
#if defined(CONFIG_ENABLE_MMU)
#include <asm/proc/domain.h>
#endif
#include <regs.h>

#ifndef CONFIG_ENABLE_MMU
#ifndef CFG_PHY_UBOOT_BASE
#define CFG_PHY_UBOOT_BASE	CFG_UBOOT_BASE
#endif /* CFG_PHY_UBOOT_BASE */
#endif /* CONFIG_ENABLE_MMU */

/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/

#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
.word 0x2000
.word 0x0
.word 0x0
.word 0x0
#endif

/******************************************************************************
* .global关键字,相当于C语言extern,全局变量,外部可访问
* _start程序入口,即uboot代码的开始。_start后面“:”标号,类似C中goto后面标号
* _start的值就是代码的最起始,相对0的位置;跳转到reset这个标号执行,即复位向量
* ARM上电复位后,从0x00000000执行,跳转到reset,不会执行异常向量表这部分。
*
* 异常向量表:未定义指令异常、软中断异常、预处理指令异常、未使用、数据异常、
* 中断异常、快速中断异常;每条占一字节,地址范围为0x0000 0000~0x0000 0020
* 设置异常向量表的作用是识别bootloader。以后系统每当有异常出现,
* 则CPU会根据异常号,从内存的0x00000000处开始查表做相应的处理
*******************************************************************************/
.globl _start
_start: b	reset   @相对跳转,不能用绝对跳转,因为启动代码有可能还运行在IRAM(s5pv210内部的SRAM)
ldr	pc, _undefined_instruction
ldr	pc, _software_interrupt
ldr	pc, _prefetch_abort
ldr	pc, _data_abort
ldr	pc, _not_used
ldr	pc, _irq
ldr	pc, _fiq

@ .word伪操作,为分配一段字(4字节)内存单元
@ 用C表示:pc = *(_x) = x  x=异常向量
_undefined_instruction:
.word undefined_instruction
_software_interrupt:
.word software_interrupt
_prefetch_abort:
.word prefetch_abort
_data_abort:
.word data_abort
_not_used:
.word not_used
_irq:
.word irq
_fiq:
.word fiq
_pad:
@ 这填写的只是一个初始值,填充4字节
.word 0x12345678 /* now 16*4=64 */
.global _end_vect  @ 异常向量结束标号
_end_vect:

@ 表示接下来的代码使用16字节对齐,不足的使用0xdeadbeef填充(坏牛肉)
@ 类似的还有一个0xbadc0de  坏代码(哈哈),十六进制没有o,是数字0
.balignl 16,0xdeadbeef
/*
*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* setup Memory and board specific bits prior to relocation.
* relocate armboot to ram
* setup stack
*
*************************************************************************
*/
@ 代码段基地址,board\samsung\TQ210\config.mk中定义,TEXT_BASE=0x23e00000
_TEXT_BASE:
.word	TEXT_BASE

/*
* Below variable is very important because we use MMU in U-Boot.
* Without it, we cannot run code correctly before MMU is ON.
* by scsuh.
*/
_TEXT_PHY_BASE:
.word	CFG_PHY_UBOOT_BASE

@ *(_armboot_start) = _start
.globl _armboot_start
_armboot_start:
.word _start

/*
* These are defined in the board-specific linker script.
*/
@ 栈头和栈尾定义在链接脚本里:board\samsung\TQ210\u-boot.lds
.globl _bss_start
_bss_start:
.word __bss_start

.globl _bss_end
_bss_end:
.word _end

@ 中断的堆栈设置,在cpu_init中用到
#if defined(CONFIG_USE_IRQ)
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word	0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif /* CONFIG_USE_IRQ */

/*
* the actual reset code
*/

@ ARM复位执行就是这里的程序,上面那部分异常只有在异常发生才会执行
reset:
/*
* set the cpu to SVC32 mode and IRQ & FIQ disable
*/
@;mrs	r0,cpsr
@;bic	r0,r0,#0x1f
@;orr	r0,r0,#0xd3
@;msr	cpsr,r0
@ 置cpu到svc32模式,关闭中断;msr将0xd3写到cpsr_c
31	30	29	28	---	7	6	-	4	3	2	1	0	说明
N	Z	C	V	 I	F	 	M4	M3	M2	M1	M0
0	0	0	0	0	User模式
0	0	0	0	1	FIQ模式
0	0	0	1	0	IRQ模式
0	0	0	1	1	SVC模式
1	0	0	0	0	User模式
1	0	0	0	1	FIQ模式
1	0	0	1	0	IRQ模式
1	0	0	1	1	SVC模式
1	0	1	1	1	ABT模式
1	1	0	1	1	UND模式
msr		cpsr_c, #0xd3		@ I & F disable, Mode: 0x13 - SVC   1101 0011

/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
@ cpu初始化
cpu_init_crit:
@ CONFIG_EVT1定义了,这段不执行
#ifndef CONFIG_EVT1
#if 0
bl	v7_flush_dcache_all
#else
bl	disable_l2cache

mov	r0, #0x0	@
mov	r1, #0x0	@ i
mov	r3, #0x0
mov	r4, #0x0
lp1:
mov	r2, #0x0	@ j
lp2:
mov	r3, r1, LSL #29		@ r3 = r1(i) <<29
mov	r4, r2, LSL #6		@ r4 = r2(j) <<6
orr	r4, r4, #0x2		@ r3 = (i<<29)|(j<<6)|(1<<1)
orr	r3, r3, r4
mov	r0, r3			@ r0 = r3
bl	CoInvalidateDCacheIndex
add	r2, #0x1		@ r2(j)++
cmp	r2, #1024		@ r2 < 1024
bne	lp2			@ jump to lp2
add	r1, #0x1		@ r1(i)++
cmp	r1, #8			@ r1(i) < 8
bne	lp1			@ jump to lp1

bl	set_l2cache_auxctrl

bl	enable_l2cache
#endif
#endif

bl	disable_l2cache   @ 关闭I/D-cache

bl	set_l2cache_auxctrl_cycle

bl	enable_l2cache    @ 使能I/D-cache

/*
* Invalidate L1 I/D
*/
@ ARM Architecture Reference Manual.pdf的745页有例子,可以搜索CP15
@ CP15 —系统控制协处理器 (the system control coprocessor)
@ 通过协处理器指令MCR和MRC提供具体的寄存器来配置和控制caches、MMU、保护系统、配置时钟模式(在bootloader时钟初始化用到)
@ Register 7 - Cache control   Register 8 - TLB operations
mov	r0, #0                  @ set up for MCR
mcr	p15, 0, r0, c8, c7, 0   @ invalidate TLBs  关闭TLB 缓冲页表(虚拟机地址转物理地址的表)的cache
mcr	p15, 0, r0, c7, c5, 0   @ invalidate icache icache 缓冲指令的I-cache

/*
* disable MMU stuff and caches
*/
@ 关闭MMU和cache --- 分析cp15的寄存器1
mrc	p15, 0, r0, c1, c0, 0
bic	r0, r0, #0x00002000     @ clear bits 13 (--V-)
bic	r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
orr	r0, r0, #0x00000002     @ set bit 1 (--A-) Align
orr	r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
mcr 	p15, 0, r0, c1, c0, 0

/* Read booting information */
ldr	r0, =PRO_ID_BASE
ldr	r1, [r0,#OMR_OFFSET]
bic	r2, r1, #0xffffffc1

/*电源管理,保持供电*/
#ifdef CONFIG_TQ210_IIC_PM_CHIP
/* PS_HOLD(GPJ2_5) set to output high */
ldr		r0, =ELFIN_GPIO_BASE
ldr		r1, =0x00100000
str		r1, [r0, #GPJ2CON_OFFSET]

ldr		r1, =0x0400
str		r1, [r0, #GPJ2PUD_OFFSET]

ldr		r1, =0x20
str		r1, [r0, #GPJ2DAT_OFFSET]
#endif /* CONFIG_TQ210_IIC_PM_CHIP */

#ifdef CONFIG_VOGUES
/* PS_HOLD(GPH0_0) set to output high */
ldr	r0, =ELFIN_GPIO_BASE
ldr	r1, =0x00000001
str	r1, [r0, #GPH0CON_OFFSET]

ldr	r1, =0x5500
str	r1, [r0, #GPH0PUD_OFFSET]

ldr	r1, =0x01
str	r1, [r0, #GPH0DAT_OFFSET]
#endif
@ 启动方式nand,SD,nor
/* NAND BOOT */
cmp	r2, #0x0		@ 512B 4-cycle
moveq	r3, #BOOT_NAND

cmp	r2, #0x2		@ 2KB 5-cycle
moveq	r3, #BOOT_NAND

cmp	r2, #0x4		@ 4KB 5-cycle	8-bit ECC
moveq	r3, #BOOT_NAND

cmp	r2, #0x6		@ 4KB 5-cycle	16-bit ECC
moveq	r3, #BOOT_NAND

cmp	r2, #0x8		@ OneNAND Mux
moveq	r3, #BOOT_ONENAND

/* SD/MMC BOOT */
cmp     r2, #0xc
moveq   r3, #BOOT_MMCSD

/* NOR BOOT */
cmp     r2, #0x14
moveq   r3, #BOOT_NOR

#if 0	/* Android C110 BSP uses OneNAND booting! */
/* For second device booting */
/* OneNAND BOOTONG failed */
cmp     r2, #0x8
moveq   r3, #BOOT_SEC_DEV
#endif

/* Uart BOOTONG failed */
cmp     r2, #(0x1<<4)
moveq   r3, #BOOT_SEC_DEV

ldr	r0, =INF_REG_BASE
str	r3, [r0, #INF_REG3_OFFSET]

/*
* Go setup Memory and board specific bits prior to relocation.
*/

ldr	sp, =0xd0036000 /* end of sram dedicated to u-boot */
sub	sp, sp, #12	/* set stack */
mov	fp, #0

@ 跳到底层硬件初始化,这部分代码在自己建立的开发板目录下的lowlevel_init.S中
@ 会返回
bl	lowlevel_init	/* go setup pll,mux,memory */
/* To hold max8698 output before releasing power on switch,
* set PS_HOLD signal to high
*/

ldr	r0, =0xE010E81C  /* PS_HOLD_CONTROL register */
ldr	r1, =0x00005301	 /* PS_HOLD output high	*/
str	r1, [r0]

/* get ready to call C functions */
ldr	sp, _TEXT_PHY_BASE	/* setup temp stack pointer */
sub	sp, sp, #12
mov	fp, #0			/* no previous frame, so fp=0 */

/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
@ 比较r1和r2,拷贝到sram
ldr	r0, =0xff000fff
bic	r1, pc, r0		/* r0 <- current base addr of code */
ldr	r2, _TEXT_BASE		/* r1 <- original base addr in ram */
bic	r2, r2, r0		/* r0 <- current base addr of code */
cmp     r1, r2                  /* compare r0, r1                  */
beq     after_copy		/* r0 == r1 then skip flash copy   */

#if defined(CONFIG_EVT1)
/* If BL1 was copied from SD/MMC CH2 */
ldr	r0, =0xD0037488
ldr	r1, [r0]
ldr	r2, =0xEB200000
cmp	r1, r2
beq     mmcsd_boot
#endif

ldr		r0, =INF_REG_BASE
ldr		r1, [r0, #INF_REG3_OFFSET]
cmp		r1, #BOOT_NAND		/* 0x0 => boot device is nand */
beq		nand_boot
cmp		r1, #BOOT_ONENAND	/* 0x1 => boot device is onenand */
beq		onenand_boot
cmp		r1, #BOOT_MMCSD
beq		mmcsd_boot
cmp		r1, #BOOT_NOR
beq		nor_boot
cmp		r1, #BOOT_SEC_DEV
beq		mmcsd_boot

nand_boot:

mov		r0, #0x1000
bl		copy_from_nand
b		after_copy

onenand_boot:
bl		onenand_bl2_copy
b		after_copy

mmcsd_boot:
#if DELETE
ldr		sp, _TEXT_PHY_BASE
sub		sp, sp, #12
mov		fp, #0
#endif
bl		movi_bl2_copy
b		after_copy

nor_boot:
bl		read_hword
b		after_copy

after_copy:

#if defined(CONFIG_ENABLE_MMU)
enable_mmu:
/* enable domain access */
ldr	r5, =0x0000ffff
mcr	p15, 0, r5, c3, c0, 0		@load domain access register

/* Set the TTB register */
ldr	r0, _mmu_table_base
ldr	r1, =CFG_PHY_UBOOT_BASE
ldr	r2, =0xfff00000
bic	r0, r0, r2
orr	r1, r0, r1
mcr	p15, 0, r1, c2, c0, 0

/* Enable the MMU */
mmu_on:
mrc	p15, 0, r0, c1, c0, 0
orr	r0, r0, #1
mcr	p15, 0, r0, c1, c0, 0
nop
nop
nop
nop
#endif

skip_hw_init:
/* Set up the stack						    */
@ 初始化栈,为第二阶段的C语言部分做准备
stack_setup:
#if defined(CONFIG_MEMORY_UPPER_CODE)
ldr	sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)
#else
ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
sub	r0, r0, #CFG_MALLOC_LEN	/* malloc area                      */
sub	r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
#if defined(CONFIG_USE_IRQ)
sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub	sp, r0, #12		/* leave 3 words for abort-stack    */

#endif
@ 清楚堆栈
clear_bss:
ldr	r0, _bss_start		/* find start of bss segment        */
ldr	r1, _bss_end		/* stop here                        */
mov 	r2, #0x00000000		/* clear                            */

@ 初始化直接使用双字,一次就是64个位
clbss_l:
str	r2, [r0]		/* clear loop...                    */
add	r0, r0, #4
cmp	r0, r1
ble	clbss_l

ldr	pc, _start_armboot @ 跳转到stage2

_start_armboot:
.word start_armboot

#if defined(CONFIG_ENABLE_MMU)
_mmu_table_base:
.word mmu_table
#endif

/*
* copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND)
* r0: size to be compared
* Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size
*/
.globl copy_from_nand
copy_from_nand:
push	{lr}		/* save return address */

mov	r9, r0

mov	r9, #0x100		/* Compare about 8KB */
bl	copy_uboot_to_ram
tst 	r0, #0x0
bne	copy_failed

#if defined(CONFIG_EVT1)
ldr	r0, =0xd0020000
#else
ldr	r0, =0xd0030000
#endif
ldr	r1, _TEXT_PHY_BASE	/* 0x23e00000 */

#if !defined(CONFIG_SECURE_BOOT)
1:	ldr	r3, [r0], #4
ldr	r4, [r1], #4
teq	r3, r4
bne	compare_failed	/* not matched */
subs	r9, r9, #4
bne	1b
#endif
pop	{pc}		/* all is OK */

copy_failed:
/**************lhh add start******************/
ldr r0,= 0xE0200080
ldr	r1, =(0x11<<12)
str	r1, [r0, #0]
ldr	r1, =(0x2<<3)
str	r1, [r0, #4]
/**************lhh add end *******************/

nop			/* copy from nand failed */
b	copy_failed

compare_failed:
nop			/* compare failed */
b	compare_failed

/*
* we assume that cache operation is done before. (eg. cleanup_before_linux())
* actually, we don't need to do anything about cache if not use d-cache in U-Boot
* So, in this function we clean only MMU. by scsuh
*
* void	theLastJump(void *kernel, int arch_num, uint boot_params);
*/
#if defined(CONFIG_ENABLE_MMU)
.globl theLastJump
theLastJump:
mov	r9, r0
ldr	r3, =0xfff00000
ldr	r4, _TEXT_PHY_BASE
adr	r5, phy_last_jump
bic	r5, r5, r3
orr	r5, r5, r4
mov	pc, r5
phy_last_jump:
/*
* disable MMU stuff
*/
mrc	p15, 0, r0, c1, c0, 0
bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
mcr	p15, 0, r0, c1, c0, 0

mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */

mov	r0, #0
mov	pc, r9
#endif
/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE	72

#define S_OLD_R0	68
#define S_PSR		64
#define S_PC		60
#define S_LR		56
#define S_SP		52

#define S_IP		48
#define S_FP		44
#define S_R10		40
#define S_R9		36
#define S_R8		32
#define S_R7		28
#define S_R6		24
#define S_R5		20
#define S_R4		16
#define S_R3		12
#define S_R2		8
#define S_R1		4
#define S_R0		0

#define MODE_SVC 0x13
#define I_BIT	 0x80

/*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/

.macro	bad_save_user_regs
sub	sp, sp, #S_FRAME_SIZE		@ carve out a frame on current user stack
stmia	sp, {r0 - r12}			@ Save user registers (now in svc mode) r0-r12

ldr	r2, _armboot_start
sub	r2, r2, #(CFG_MALLOC_LEN)
sub	r2, r2, #(CFG_GBL_DATA_SIZE+8)	@ set base 2 words into abort stack
ldmia	r2, {r2 - r3}			@ get values for "aborted" pc and cpsr (into parm regs)
add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack

add	r5, sp, #S_SP
mov	r1, lr
stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr
mov	r0, sp				@ save current stack into r0 (param register)
.endm

.macro	irq_save_user_regs
sub	sp, sp, #S_FRAME_SIZE
stmia	sp, {r0 - r12}			@ Calling r0-r12
add	r8, sp, #S_PC			@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
stmdb	r8, {sp, lr}^			@ Calling SP, LR
str	lr, [r8, #0]			@ Save calling PC
mrs	r6, spsr
str	r6, [r8, #4]			@ Save CPSR
str	r0, [r8, #8]			@ Save OLD_R0
mov	r0, sp
.endm

.macro	irq_restore_user_regs
ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
mov	r0, r0
ldr	lr, [sp, #S_PC]			@ Get PC
add	sp, sp, #S_FRAME_SIZE
subs	pc, lr, #4			@ return & move spsr_svc into cpsr
.endm

.macro get_bad_stack
ldr	r13, _armboot_start		@ setup our mode stack (enter in banked mode)
sub	r13, r13, #(CFG_MALLOC_LEN)	@ move past malloc pool
sub	r13, r13, #(CFG_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack

str	lr, [r13]			@ save caller lr in position 0 of saved stack
mrs	lr, spsr			@ get the spsr
str	lr, [r13, #4]			@ save spsr in position 1 of saved stack

mov	r13, #MODE_SVC			@ prepare SVC-Mode
@ msr	spsr_c, r13
msr	spsr, r13			@ switch modes, make sure moves will execute
mov	lr, pc				@ capture return pc
movs	pc, lr				@ jump to next instruction & switch modes.
.endm

.macro get_bad_stack_swi
sub	r13, r13, #4			@ space on current stack for scratch reg.
str	r0, [r13]			@ save R0's value.
ldr	r0, _armboot_start		@ get data regions start
sub	r0, r0, #(CFG_MALLOC_LEN)	@ move past malloc pool
sub	r0, r0, #(CFG_GBL_DATA_SIZE+8)	@ move past gbl and a couple spots for abort stack
str	lr, [r0]			@ save caller lr in position 0 of saved stack
mrs	r0, spsr			@ get the spsr
str	lr, [r0, #4]			@ save spsr in position 1 of saved stack
ldr	r0, [r13]			@ restore r0
add	r13, r13, #4			@ pop stack entry
.endm

.macro get_irq_stack			@ setup IRQ stack
ldr	sp, IRQ_STACK_START
.endm

.macro get_fiq_stack			@ setup FIQ stack
ldr	sp, FIQ_STACK_START
.endm

/*
* exception handlers
*/
.align	5                       @32字节对齐
undefined_instruction:
get_bad_stack                   @宏,保存现场栈
bad_save_user_regs              @宏,保存现场
bl	do_undefined_instruction    @宏,答应现场

.align	5
software_interrupt:
get_bad_stack_swi
bad_save_user_regs
bl	do_software_interrupt

.align	5
prefetch_abort:
get_bad_stack
bad_save_user_regs
bl	do_prefetch_abort

.align	5
data_abort:
get_bad_stack
bad_save_user_regs
bl	do_data_abort

.align	5
not_used:
get_bad_stack
bad_save_user_regs
bl	do_not_used

#if defined(CONFIG_USE_IRQ)

.align	5
irq:
get_irq_stack
irq_save_user_regs
bl	do_irq
irq_restore_user_regs

.align	5
fiq:
get_fiq_stack
/* someone ought to write a more effiction fiq_save_user_regs */
irq_save_user_regs
bl	do_fiq
irq_restore_user_regs

#else

.align	5
irq:
get_bad_stack
bad_save_user_regs
bl	do_irq

.align	5
fiq:
get_bad_stack
bad_save_user_regs
bl	do_fiq

#endif
.align 5
.global arm_cache_flush
arm_cache_flush:
mcr     p15, 0, r1, c7, c5, 0           @ invalidate I cache
mov     pc, lr                          @ back to caller

/*
*     v7_flush_dcache_all()
*
*     Flush the whole D-cache.
*
*     Corrupted registers: r0-r5, r7, r9-r11
*
*     - mm    - mm_struct describing address space
*/
.align 5
.global v7_flush_dcache_all
v7_flush_dcache_all:

ldr	r0, =0xffffffff
mrc	p15, 1, r0, c0, c0, 1 		@ Read CLIDR
ands	r3, r0, #0x7000000
mov	r3, r3, LSR #23       		@ Cache level value (naturally aligned)
beq 	Finished
mov	r10, #0
Loop1:
add	r2, r10, r10, LSR #1  		@ Work out 3xcachelevel
mov	r1, r0, LSR r2        		@ bottom 3 bits are the Ctype for this level
and	r1, r1, #7            		@ get those 3 bits alone
cmp	r1, #2
blt	Skip                   		@ no cache or only instruction cache at this level
mcr	p15, 2, r10, c0, c0, 0 		@ write the Cache Size selection register
mov	r1, #0
mcr	p15, 0, r1, c7, c5, 4 		@ PrefetchFlush to sync the change to the CacheSizeID reg
mrc	p15, 1, r1, c0, c0, 0 		@ reads current Cache Size ID register
and	r2, r1, #0x7           		@ extract the line length field
add	r2, r2, #4            		@ add 4 for the line length offset (log2 16 bytes)
ldr	r4, =0x3FF
ands	r4, r4, r1, LSR #3   		@ R4 is the max number on the way size (right aligned)
clz	r5, r4                		@ R5 is the bit position of the way size increment
ldr	r7, =0x00007FFF
ands	r7, r7, r1, LSR #13  		@ R7 is the max number of the index size (right aligned)
Loop2:
mov	r9, r4                      	@ R9 working copy of the max way size (right aligned)
Loop3:
orr	r11, r10, r9, LSL r5        	@ factor in the way number and cache number into R11
orr	r11, r11, r7, LSL r2        	@ factor in the index number
mcr	p15, 0, r11, c7, c6, 2 		@ invalidate by set/way
subs	r9, r9, #1                 	@ decrement the way number
bge	Loop3
subs	r7, r7, #1                 	@ decrement the index
bge	Loop2
Skip:
add	r10, r10, #2                	@ increment the cache number
cmp	r3, r10
bgt	Loop1
Finished:
mov	pc, lr

.align  5
.global disable_l2cache
disable_l2cache:
mrc     p15, 0, r0, c1, c0, 1
bic     r0, r0, #(1<<1)
mcr     p15, 0, r0, c1, c0, 1
mov	pc, lr

.align  5
.global enable_l2cache
enable_l2cache:
mrc     p15, 0, r0, c1, c0, 1
orr     r0, r0, #(1<<1)
mcr     p15, 0, r0, c1, c0, 1
mov     pc, lr

.align  5
.global set_l2cache_auxctrl
set_l2cache_auxctrl:
mov	r0, #0x0
mcr     p15, 1, r0, c9, c0, 2
mov     pc, lr

.align  5
.global set_l2cache_auxctrl_cycle
set_l2cache_auxctrl_cycle:
mrc 	p15, 1, r0, c9, c0, 2
bic 	r0, r0, #(0x1<<29)
bic 	r0, r0, #(0x1<<21)
bic 	r0, r0, #(0x7<<6)
bic 	r0, r0, #(0x7<<0)
mcr 	p15, 1, r0, c9, c0, 2
mov     pc,lr

.align 5
CoInvalidateDCacheIndex:
;/* r0 = index */
mcr     p15, 0, r0, c7, c6, 2
mov     pc,lr

#if defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_CINTEGRATOR)
/* Use the IntegratorCP function from board/integratorcp/platform.S */
#elif defined(CONFIG_S5PC11X)
/* For future usage of S3C64XX*/
#else
.align	5
.globl reset_cpu
reset_cpu:
ldr	r1, rstctl	/* get addr for global reset reg */
mov	r3, #0x2	/* full reset pll+mpu */
str	r3, [r1]	/* force reset */
mov	r0, r0
_loop_forever:
b	_loop_forever
rstctl:
.word	PM_RSTCTRL_WKUP

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息