最近在看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]
看下面這個圖:
/* 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