三星uboot-1.1.6源码分析——lowlevel_init.S (board\samsung\smdk6410)(1)

时间:2021-11-10 20:26:54

最近在看uboot的源码,做些笔记。

lowlevel_init.S (board\samsung\smdk6410)这个文件主要是与板级配置相关的代码,看他在那个目录就知道了。不多说了,开始看源码。

1、

#include <config.h>
#include <version.h>

#include <s3c6410.h>
#include "smdk6410_val.h"

_TEXT_BASE:
.word TEXT_BASE

.globl lowlevel_init
lowlevel_init:
mov r12, lr  保存PC的值


ldr r0, =ELFIN_GPIO_BASE
ldr     r1, =0x55555555
str     r1, [r0, #GPKCON0_OFFSET]


ldr     r1, =0x55555555
str     r1, [r0, #GPKCON1_OFFSET]


ldr     r1, =0x22222666
str     r1, [r0, #GPLCON0_OFFSET]

ldr     r1, =0x04000000
str     r1, [r0, #GPFCON_OFFSET]
        ldr     r1, =0x2000
str     r1, [r0, #GPFDAT_OFFSET]

上面这一段,是根据具体的开发板添加的,如飞凌的就与外设扩展的接口键盘和WIFI接口有关。

  /* LED on only #8 */   对驱动LED的GPIO进行一定的初始化
ldr r0, =ELFIN_GPIO_BASE  
ldr r1, =0x00111111
str r1, [r0, #GPMCON_OFFSET]


ldr r1, =0x00000555
str r1, [r0, #GPMPUD_OFFSET]


ldr r1, =0x002a
str r1, [r0, #GPMDAT_OFFSET]

 下面这个这个和MEM1DRVCON寄存器有关,Memory Port 1 Drive strength Control Register,主要是关于Memory port 1驱动电流的选择。
ldr r1, =0  /*0x55555555 phantom*/
str r1, [r0, #MEM1DRVCON_OFFSET]

看下面这个图:

三星uboot-1.1.6源码分析——lowlevel_init.S (board\samsung\smdk6410)(1)三星uboot-1.1.6源码分析——lowlevel_init.S (board\samsung\smdk6410)(1)


/* Disable Watchdog */
ldr r0, =0x7e000000@0x7e004000
orr r0, r0, #0x4000
mov r1, #0
str r1, [r0]
上面这一段是关闭看门狗,如果你仔细看start.s的源码,会发现同样有一段代码说是关闭看门狗,但那个就看不懂了,我也列出来做个对比,如果你知道,可以告诉我。

start.S (cpu\s3c64xx)
#if defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)
orr r0, r0, #300@ disable watchdog
mov r1, #1
str r1, [r0]


@ External interrupt pending clear   外部中断挂起寄存器清零,先读出寄存器的值,如后回写就可以了。因为这个寄存器是写1,清零,看下这个寄存器NOTES,就可知道。 NOTES: 1. Each bit is cleared by writing "1"
ldrr0, =(ELFIN_GPIO_BASE+EINTPEND_OFFSET)/*EINTPEND*/
ldrr1, [r0]
strr1, [r0]


ldrr0, =ELFIN_VIC0_BASE_ADDR@0x71200000
ldrr1, =ELFIN_VIC1_BASE_ADDR@0x71300000

• Base address of VIC0 is 0x7120_0000
• Base address of VIC1 is 0x7130_0000
• Address of control register = base address + offset



@ Disable all interrupts (VIC0 and VIC1)
mvnr3, #0x0  这里说下这个mvn指令,它与mov的不同之处在于,先把源操作寄存器的内容取反,再送到目的寄存器
strr3, [r0, #oINTMSK]
strr3, [r1, #oINTMSK]


@ Set all interrupts as IRQ
movr3, #0x0
strr3, [r0, #oINTMOD]
strr3, [r1, #oINTMOD]


@ Pending Interrupt Clear
movr3, #0x0
strr3, [r0, #oVECTADDR]
strr3, [r1, #oVECTADDR]

2、

/* init system clock */
bl system_clock_init

去看system_clock_init的源码,在同一个文件中,如下所示:

s3c6410手册中,与时钟有关的部分主要在 第三章   SYSTEM CONTROLLER中,摘自文中的一段话:

The System Clock Control logic in 6410 generates the required system clock signals, ARMCLK for CPU, HCLK for AXI/AHB-bus peripherals, and PCLK for the APB bus peripherals. There are three PLLs in 6410. One is for ARMCLK only. Second is for HCLK and PCLK. The third thing is for peripheral, especially for audio related clocks.The clock control logic generates slow-rate clock-signals for ARMCLK, HCLK and PCLK by bypassing externally supplied clock sources. The clock signal to each peripheral block can be enabled or disabled by software control to reduce the power consumption.

/*
 * system_clock_init: Initialize core clock and bus clock.
 * void system_clock_init(void)
 */
system_clock_init:
ldr r0, =ELFIN_CLOCK_POWER_BASE  @0x7e00f000

这个地址是APLL_LOCK寄存器的地址,作为基地址

下面这段代码都是和时钟有关,在此之前先来说下ASYNC MODE和SYNC MODE的去别,看下面:

S3C6410 has APLL and MPLL, so you can use that MPLL is source for HCLK, PCLK, etc.(ASYNC mode).
In default configuration setting is SYNC mode APLL support main clock for FCLK, HCLK, PCLK, etc. If
you want to use ASYNC mode, you have to disabling definition for SMDK6410 SYNC mode selection
in “include/configs/smdk6410.h”

#define CONFIG_SYNC_MODE

应该大致明白了吧,同时在Smdk6410.h (include\configs)文件中,有如下定义,

#if defined(CONFIG_CLK_666_133_66) /* FIN 12MHz, Fout 666MHz */
#define APLL_MDIV 333
#define APLL_PDIV 3
#define APLL_SDIV 1
#undef  CONFIG_SYNC_MODE /* ASYNC MODE */


#elif defined(CONFIG_CLK_532_133_66) /* FIN 12MHz, Fout 532MHz */
#define APLL_MDIV 266
#define APLL_PDIV 3
#define APLL_SDIV 1
#define CONFIG_SYNC_MODE


#elif defined(CONFIG_CLK_400_133_66) || defined(CONFIG_CLK_800_133_66) /* FIN 12MHz, Fout 800MHz */
#define APLL_MDIV 400
#define APLL_PDIV 3
#define APLL_SDIV 1
#define CONFIG_SYNC_MODE


#elif defined(CONFIG_CLK_400_100_50) /* FIN 12MHz, Fout 400MHz */
#define APLL_MDIV 400
#define APLL_PDIV 3
#define APLL_SDIV 2
#define CONFIG_SYNC_MODE


#elif defined(CONFIG_CLK_OTHERS)
/*If you have to use another value, please define pll value here*/
/* FIN 12MHz, Fout 532MHz */
#define APLL_MDIV 266
#define APLL_PDIV 3
#define APLL_SDIV 1
#define CONFIG_SYNC_MODE

#else
#error "Not Support Fequency or Mode!! you have to setup right configuration."
#endif

上面这段代码说明什么呢?

SYNC mode is supported under FCLK 532 ㎒等. If you want to use FCLK 667 ㎒, you must use
ASYNC mode。

下面的源码下篇再分析:
#ifdef CONFIG_SYNC_MODE
ldr r1, [r0, #OTHERS_OFFSET]
mov r2, #0x40
orr r1, r1, r2
str r1, [r0, #OTHERS_OFFSET]


nop
nop
nop
nop
nop


ldr r2, =0x80
orr r1, r1, r2
str r1, [r0, #OTHERS_OFFSET]


check_syncack:
ldr r1, [r0, #OTHERS_OFFSET]
ldr r2, =0xf00
and r1, r1, r2
cmp r1, #0xf00
bne check_syncack
#else /* ASYNC Mode */
nop
nop
nop
nop
nop


ldr r1, [r0, #OTHERS_OFFSET]
bic r1, r1, #0xC0
orr r1, r1, #0x40
str r1, [r0, #OTHERS_OFFSET]


wait_for_async:
ldr r1, [r0, #OTHERS_OFFSET]
and r1, r1, #0xf00
cmp r1, #0x0
bne wait_for_async


ldr r1, [r0, #OTHERS_OFFSET]
bic r1, r1, #0x40
str r1, [r0, #OTHERS_OFFSET]
#endif


mov r1, #0xff00
orr r1, r1, #0xff
str r1, [r0, #APLL_LOCK_OFFSET]
str r1, [r0, #MPLL_LOCK_OFFSET]
str r1, [r0, #EPLL_LOCK_OFFSET]
/* CLKUART(=66.5Mhz) = CLKUART_input(532/2=266Mhz) / (UART_RATIO(3)+1) */
/* CLKUART(=50Mhz) = CLKUART_input(400/2=200Mhz) / (UART_RATIO(3)+1) */
/* Now, When you use UART CLK SRC by EXT_UCLK1, We support 532MHz & 400MHz value */


#if defined(CONFIG_CLKSRC_CLKUART)
ldr   r1, [r0, #CLK_DIV2_OFFSET]
bic r1, r1, #0x70000
orr r1, r1, #0x30000
str r1, [r0, #CLK_DIV2_OFFSET]
#endif




ldr   r1, [r0, #CLK_DIV0_OFFSET]/*Set Clock Divider*/
bic r1, r1, #0x30000
bic r1, r1, #0xff00
bic r1, r1, #0xff
ldr r2, =CLK_DIV_VAL
orr r1, r1, r2
str r1, [r0, #CLK_DIV0_OFFSET]


ldr r1, =APLL_VAL
str r1, [r0, #APLL_CON_OFFSET]
ldr r1, =MPLL_VAL
str r1, [r0, #MPLL_CON_OFFSET]


ldr r1, =0x80200203/* FOUT of EPLL is 96MHz */
str r1, [r0, #EPLL_CON0_OFFSET]
ldr r1, =0x0
str r1, [r0, #EPLL_CON1_OFFSET]


ldr r1, [r0, #CLK_SRC_OFFSET]/* APLL, MPLL, EPLL select to Fout */


#if defined(CONFIG_CLKSRC_CLKUART)
ldr r2, =0x2007
#else
ldr r2, =0x7
#endif
orr r1, r1, r2


str r1, [r0, #CLK_SRC_OFFSET]


/* wait at least 200us to stablize all clock */
mov r1, #0x10000
1: subs r1, r1, #1
bne 1b
#if 0
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0xc0000000/* clock setting in MMU */
mcr p15, 0, r0, c1, c0, 0
#endif


#ifdef CONFIG_SYNC_MODE /* Synchronization for VIC port */
ldr r1, [r0, #OTHERS_OFFSET]
orr r1, r1, #0x20
str r1, [r0, #OTHERS_OFFSET]
#else
ldr r1, [r0, #OTHERS_OFFSET]
bic r1, r1, #0x20
str r1, [r0, #OTHERS_OFFSET]
#endif
mov pc, lr

三星uboot-1.1.6源码分析——lowlevel_init.S (2)——时钟配置的链接地址

三星uboot-1.1.6源码分析——lowlevel_init.S (3)---串口的链接地址