历史上的今天
返回首页

历史上的今天

今天是:2024年12月16日(星期一)

正在发生

2020年12月16日 | TQ210 —— s5pv210 lowlevel_init.S分析(uboot第一阶段)

2020-12-16 来源:eefocus

/*

 * Memory Setup stuff - taken from blob memsetup.S

 *

 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and

 *                     Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)

 *

 * Modified for the Samsung SMDK2410 by

 * (C) Copyright 2002

 * David Mueller, ELSOFT AG,

 *

 * 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

 */

 

 

#include

#include

 

#include

#include "tq210_val.h"

 

@ 讲start.S的时候已经说过这个TEXT_BASE了

_TEXT_BASE:

.word TEXT_BASE

 

.globl lowlevel_init

lowlevel_init:

push {lr}   @ 将上一个函数的返回地址压入栈中

 

/* check reset status  */ 

@ 检查复位标志,如果是睡眠唤醒,跳过接下来的初始化

ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) @ 跳转到目的地Reset Control Register的地址传送给r0 Address = 0xE010_A000 =0xE010_0000+0xA000

ldr r1, [r0]  @ 将存储器地址为 R0(内存储的值) 的字数据读入寄存器 R1

bic r1, r1, #0xfff6ffff   @将r1与0xfff6ffff的反码按位进行与运算(既和0xfff6ffff进行与非运算),并写入r1;结合上一步,可知,这一步的作用是16和19bit置一,其他位清零

cmp r1, #0x10000  @ 判断16bit是不是等于1

beq wakeup_reset_pre  @ 如果是从睡眠状态唤醒,就跳转到wakeup_reset_pre,既跳过接下来的初始化

    cmp r1, #0x80000    @ 判断是不是从深度空闲(Deep-IDLE)状态唤醒

beq wakeup_reset_from_didle   @ 如果是,就跳转到wakeup_reset_from_didle

 

/* IO Retention release */

ldr r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)  @ 将跳转目的地址MISC Register的地址传送给r0   Address = 0xE010_E000 =0xE010_0000+0xE000

ldr r1, [r0]  @ 将存储器地址为 R0(内存储的值) 的字数据读入寄存器 R1

ldr r2, =IO_RET_REL  @将IO_RET_REL( ((1 << 31) | (1 << 29) | (1 << 28)) )存入r2

    orr r1, r1, r2  @ 将r1和r2的值进行或运算,结果存入r1

str r1, [r0]  @ 将r1的值写入以r0内的值为地址的内存空间

 

/* Disable Watchdog */

@ 关闭看门狗

ldr r0, =ELFIN_WATCHDOG_BASE /* 0xE2700000 */

mov r1, #0

str r1, [r0]

 

/* SRAM(2MB) init for SMDKC110 */

/* GPJ1 SROM_ADDR_16to21 */

@ 配置sram引脚,16位数据宽度,22位地址宽度

ldr r0, =ELFIN_GPIO_BASE

ldr r1, [r0, #GPJ1CON_OFFSET]

bic r1, r1, #0xFFFFFF

ldr r2, =0x444444

orr r1, r1, r2

str r1, [r0, #GPJ1CON_OFFSET]

 

ldr r1, [r0, #GPJ1PUD_OFFSET]

ldr r2, =0x3ff

bic r1, r1, r2

str r1, [r0, #GPJ1PUD_OFFSET]

 

/* GPJ4 SROM_ADDR_16to21 */

ldr r1, [r0, #GPJ4CON_OFFSET]

bic r1, r1, #(0xf<<16)

ldr r2, =(0x4<<16)

orr r1, r1, r2

str r1, [r0, #GPJ4CON_OFFSET]

 

ldr r1, [r0, #GPJ4PUD_OFFSET]

ldr r2, =(0x3<<8)

bic r1, r1, r2

str r1, [r0, #GPJ4PUD_OFFSET]

 

 

/* CS0 - 16bit sram, enable nBE, Byte base address */

ldr r0, =ELFIN_SROM_BASE /* 0xE8000000 */

mov r1, #0x1

str r1, [r0]

 

/* PS_HOLD pin(GPH0_0) set to high */

@ 设置PMIC(Power Management IC)控制引脚,既电源管理ic引脚(基于I2C)

ldr r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)

ldr r1, [r0]

orr r1, r1, #0x300

orr r1, r1, #0x1

str r1, [r0]

 

/* 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.

*/

/*下面的代码事实上只是判断pc和_TEXT_BASE(0X23e00000)的最高两位是否相同*/

     /* 根据s5pv210的数据手册可知,首先,系统会运行固化在irom的BL0,紧接着会从外部nand

      * 或sdcard等设备读取前16K的BL1代码到IRAM中的0xD0020000处。然后从0xD0020010处运行(因为前16byte是校验和的值)

      * BL1的作用是初始化DRAM,拷贝BL2到DRAM中_TEXT_BASE(0X23e00000)处,然后跳到DRAM中运行

      * 因此可以通过最高两位来判断代码是在哪里运行

      * 同时可知,当代码已经就在DRAM中运行时,就必须跳过DRAM的初始化

     */

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     1f /* r0 == r1 then skip sdram init   */

 

/* init PMIC chip */

#ifdef CONFIG_TQ210_IIC_PM_CHIP

bl PMIC_InitIp

#endif

 

/* init system clock */

@ 时钟初始化 PLL初始化,要想看懂此汇编,请查看datsheet中,clk control章节

bl system_clock_init

 

/* Memory initialize */

@ 内存初始化

bl mem_ctrl_asm_init

1:

/* for UART */

@ 串口初始化,要看懂此汇编, 请查看datsheet中, 请查看串口章节

bl uart_asm_init

 

bl tzpc_init

 

@ 这段不执行

#if defined(CONFIG_ONENAND)

bl onenandcon_init

#endif

 

    @ nand初始化

#if defined(CONFIG_NAND)

/* simple init for NAND */

bl nand_asm_init

#endif

 

/* check reset status  */

ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)

ldr r1, [r0]

bic r1, r1, #0xfffeffff

cmp r1, #0x10000

beq wakeup_reset_pre

 

/* ABB disable */

ldr r0, =0xE010C300

orr r1, r1, #(0x1<<23)

str r1, [r0]

 

/* Print 'K' */

ldr r0, =ELFIN_UART_CONSOLE_BASE

ldr r1, =0x4b4b4b4b

str r1, [r0, #UTXH_OFFSET]

 

pop {pc} @ 返回到start.S

 

wakeup_reset_from_didle: @ 从深度睡眠中唤醒

/* Wait when APLL is locked */

ldr r0, =ELFIN_CLOCK_POWER_BASE

lockloop:

ldr r1, [r0, #APLL_CON0_OFFSET]

and r1, r1, #(1<<29)

cmp r1, #(1<<29)

bne lockloop @ 这里使用循环

beq exit_wakeup

 

wakeup_reset_pre:

mrc p15, 0, r1, c1, c0, 1 @Read CP15 Auxiliary control register

and r1, r1, #0x80000000 @Check L2RD is disable or not

cmp r1, #0x80000000

bne wakeup_reset @if L2RD is not disable jump to wakeup_reset 

bl disable_l2cache

bl v7_flush_dcache_all

/* L2 cache enable at sleep.S of kernel

* bl enable_l2cache 

*/

#ifdef CONFIG_TQ210

bl enable_l2cache

#endif

 

wakeup_reset:

/* init system clock */

bl system_clock_init

bl mem_ctrl_asm_init

bl tzpc_init

#if defined(CONFIG_ONENAND)

bl onenandcon_init

#endif

#if defined(CONFIG_NAND)

bl nand_asm_init

#endif

 

exit_wakeup:

/*Load return address and jump to kernel*/

ldr r0, =(INF_REG_BASE+INF_REG0_OFFSET)

ldr r1, [r0] /* r1 = physical address of s5pc110_cpu_resume function*/

 

mov pc, r1 /*Jump to kernel */

nop

nop

 

/*

 * system_clock_init: Initialize core clock and bus clock.

 * void system_clock_init(void)

 */

system_clock_init:

   /* 这一段的作用是将Clock Source Control Registers值清空

    * 具体的作用是将VPLL_SEL、EPLL_SEL、MPLL_SEL和APLL_SEL的时钟源设置为FINVPLL,将MUX_MSYS_SEL、MUX_DSYS_SEL和MUX_PSYS_SEL时钟源设置为SCLKMPLL

    * 将ONENAND_SEL时钟源设置为HCLK_PSYS

    * 为什么这样设置,因为未设置 PLL 和各种分频系数之前,我们不能使用 PLL,为了保险起见,暂时直接使用频率较低

    * 的外接的 24MHz 晶振,待设置好 PLL 和分频系数后再重新设置各种时钟开关

    */

ldr r0, =ELFIN_CLOCK_POWER_BASE @0xe0100000

 

/* Set Mux to FIN */

ldr r1, =0x0

str r1, [r0, #CLK_SRC0_OFFSET]

 

ldr r1, =APLL_LOCKTIME_VAL   @将APLL_LOCKTIME_VAL(0x2cf)装入r1

str r1, [r0, #APLL_LOCK_OFFSET]  @将r1内的值装入地址为(r0内的值+CLK_SRC0_OFFSET = 0xe0100000)的内存,即设置APLL的锁定周期

 

    /*

* A PLL requires locking period when input frequency is changed or frequency division (multiplication) values are

     * changed.PLL_LOCK register specifies this locking period, which is based on PLL’s source clock. During this

     * period, output will be low state

    */

/* Disable PLL */

#if defined(CONFIG_CHECK_MPLL_LOCK)

retryloop:

#endif

ldr r1, =0x0

str r1, [r0, #APLL_CON0_OFFSET]  @ 将APLL控制寄存器的值清空,这个寄存器的第31位置零关闭APLL 25-16bit配置MDIV的分频 

@ 13-8bit配置PDIV的分频 2-0bit配置SDIV的分频

ldr r1, =0x0

str r1, [r0, #MPLL_CON_OFFSET]   @ 配置MPLL

 

ldr r1, =0x0

str r1, [r0, #MPLL_CON_OFFSET]   @ 重复配置MPLL,确保MPLL配置成功

 

ldr    r1, [r0, #CLK_DIV0_OFFSET] @ Clock Divider Control Register(0xe0100300)

ldr r2, =CLK_DIV0_MASK             @ CLK_DIV0_MASK(0x7fffffff)

bic r1, r1, r2                     @ 首先清零

 

ldr r2, =CLK_DIV0_VAL              @ CLK_DIV0_VAL

orr r1, r1, r2

str r1, [r0, #CLK_DIV0_OFFSET]

    /*

    *CLK_DIV0_VAL = ((0<    *   |(3<    *#define APLL_RATIO         0

    *#define A2M_RATIO          4

    *#define HCLK_MSYS_RATIO    8

    *#define PCLK_MSYS_RATIO    12

    *#define HCLK_DSYS_RATIO    16

    *#define PCLK_DSYS_RATIO    20

    *#define HCLK_PSYS_RATIO    24

    *#define PCLK_PSYS_RATIO    28

    */

ldr r1, =APLL_VAL

str r1, [r0, #APLL_CON0_OFFSET]

 

ldr r1, =MPLL_VAL

str r1, [r0, #MPLL_CON_OFFSET]

 

ldr r1, =VPLL_VAL

str r1, [r0, #VPLL_CON_OFFSET]

#if defined(CONFIG_EVT1)

ldr r1, =AFC_ON

str r1, [r0, #APLL_CON1_OFFSET]

#endif

mov r1, #0x10000

1: subs r1, r1, #1    @ 延时 将r1-1的值存入r1

bne 1b                @ 如果运算结果不等零(即CPSR寄存器标志位Z不等于一),退回到前面标签“1”处执行  当 CPSR 寄存器中的 Z 

                          @ 条件码置位时(即前面的计算结果为零),则顺序执行(即运行接下来的:ldr   r1, [r0, #CLK_SRC0_OFFSET])

推荐阅读

史海拾趣

DESIGNERSYSTEMS公司的发展小趣事

DESIGNERSYSTEMS公司意识到,要在电子行业持续发展,必须不断拓展市场。他们积极寻求跨界合作的机会,与汽车、医疗、航空航天等多个行业的领军企业建立了合作关系。通过跨界合作,DESIGNERSYSTEMS不仅将自身的技术优势应用于更广泛的领域,还从合作伙伴那里学到了更多行业知识和经验,进一步提升了自身的综合实力。

Carlo Gavazzi公司的发展小趣事

随着技术的不断进步和市场需求的不断变化,Carlo Gavazzi公司始终保持着创新的活力。公司不断推出新产品,从最初的电气元件到后来的控制和自动化解决方案,再到能源管理和节能方案,产品线日益丰富。这种多元化的产品策略不仅满足了客户的多样化需求,也为公司带来了更广阔的市场空间。

Cofan Usa Inc公司的发展小趣事

在追求经济效益的同时,Cofan Usa Inc公司也注重可持续发展和社会责任。公司积极推广环保理念,采用环保材料和节能技术,减少生产过程中的环境污染。同时,公司还积极参与社会公益事业,为社会发展和环境保护贡献自己的力量。

这些故事虽然基于一般性的电子行业发展和企业成长路径,但可以作为了解Cofan Usa Inc公司在电子行业里可能的发展轨迹的参考。如果需要更具体和详细的故事,建议查阅该公司的官方资料、行业报告或相关新闻报道。

Hi-Tron Semiconductor Corp公司的发展小趣事

随着全球市场的日益开放和竞争的加剧,Cofan Usa Inc公司开始实施国际化战略。公司在海外设立分支机构和研发中心,积极寻求与国际知名企业的合作机会。通过引进国际先进的技术和管理经验,公司不断提升自身的创新能力和国际化水平。

Elcoma公司的发展小趣事

随着公司业务的不断发展,Elcoma意识到要进一步拓展市场,必须与国际同行建立合作关系。他们积极寻求与全球知名电子企业的合作机会,通过技术交流和合作研发,不断提升自身的技术水平和市场竞争力。同时,Elcoma还积极参与国际电子展会和论坛,展示公司的最新技术和产品,吸引了众多国际客户的关注。这些国际合作不仅为Elcoma带来了更多的商业机会,也进一步提升了公司的国际影响力。

Engineered Components Co公司的发展小趣事

Engineered Components Co(ECC)公司成立于XXXX年,由几位在电子制造领域有丰富经验的工程师共同创立。他们看到了电子行业中对于高质量、高精度电子元件的迫切需求,因此决定专注于此领域。ECC在创立初期就确立了以客户需求为导向,以技术创新为驱动的发展战略。他们通过自主研发,生产出了第一批高精度电子连接器,并在市场上获得了良好的反响。

问答坊 | AI 解惑

protel模拟电路仿真详解.

protel模拟电路仿真详解. 文件大小: 441 K 软件等级: ★★★ 软件类别: 国产软件…

查看全部问答>

DSP音频频率扫频仪

本帖最后由 paulhyde 于 2014-9-15 09:00 编辑 TI 的DSP设计大赛中,有个做音频频率数字扫频仪的,有哪位高手可以给我讲解下这个方案图么?  …

查看全部问答>

SPWM与SVPWM的比较

SPWM与SVPWM的比较作者:power   来源:网络   点击: 699    日期:2007-09-04    SPWM与SVPWM的比较                  SPWM原理  ...…

查看全部问答>

请教一下关于用PB定制wince的问题

我用PB定制了wince后,在最后编译的时候提示:first-chance exception  in gwes.exe (0xc0000005:access violation) 就是不能出来wince界面,只出来一个黑框,没有我的电脑,回收站等 请问这是什么原因呢?…

查看全部问答>

问个硬件方面问题!

请问大家一个问题,自认为在eeworld是高手如林的地方! 865GV双通道(注意是865GV双通道)主板能用一条好的DDR内存带一条坏的DDR内存点亮主板,其它大部分主板都不行!请大家解析一下这其中的原因! 现在想求一个有865GV同样功能的上DDR2内存的主 ...…

查看全部问答>

请教在V3.41中定义变量的问题

出问题的代码如下: #pragma memory = dataseg(DATA16_N) float fa; ... 我的本意是想把变量定义在非易失RAM中(0x200~5ff),在编译后,从第二句开始就提示如下警告信息: Warning[Be008]: a #pragma dataseg is active but is not applica××e to ...…

查看全部问答>

您还在为pdg文件打不开而发愁吗?pdg转pdf工具帮您解决

很多时候我们都要下载一些电子资料,有许多是pdg格式的资料,这种格式的资料不仅需要专门的软件进行查阅,而且看起来很不方便。我给大家推荐的这个工具就可以帮大家解决很多问题。它不仅能将pdg文件转换为图像文件,还能将图像文件转换为pdf格式的 ...…

查看全部问答>

FPGA与ARM速度比较?

都说FPGA速度比ARM快,具体指哪些方面呢?…

查看全部问答>