#include <config.h>
#include <version.h>
#include <s3c6410.h>
#include "smdk6410_val.h"
_TEXT_BASE:
.wordTEXT_BASE
.globl lowlevel_init
lowlevel_init:
movr12, lr 保存PC的值
ldrr0, =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进行一定的初始化
ldrr0, =ELFIN_GPIO_BASE
ldrr1, =0x00111111
strr1, [r0, #GPMCON_OFFSET]
ldrr1, =0x00000555
strr1, [r0, #GPMPUD_OFFSET]
ldrr1, =0x002a
strr1, [r0, #GPMDAT_OFFSET]
下面这个这个和MEM1DRVCON寄存器有关,Memory Port 1 Drive strength Control Register,主要是关于Memory port 1驱动电流的选择。
ldrr1, =0 /*0x55555555 phantom*/
strr1, [r0, #MEM1DRVCON_OFFSET]
看下面这个图:
/* Disable Watchdog */
ldrr0, =0x7e000000@0x7e004000
orrr0, r0, #0x4000
movr1, #0
strr1, [r0]
上面这一段是关闭看门狗,如果你仔细看start.s的源码,会发现同样有一段代码说是关闭看门狗,但那个就看不懂了,我也列出来做个对比,如果你知道,可以告诉我。
start.S (cpu\s3c64xx)
#if defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)
orrr0, r0, #300@ disable watchdog
movr1, #1
strr1, [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:
ldrr0, =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_MDIV333
#define APLL_PDIV3
#define APLL_SDIV1
#undef CONFIG_SYNC_MODE /* ASYNC MODE */
#elif defined(CONFIG_CLK_532_133_66) /* FIN 12MHz, Fout 532MHz */
#define APLL_MDIV266
#define APLL_PDIV3
#define APLL_SDIV1
#define CONFIG_SYNC_MODE
#elif defined(CONFIG_CLK_400_133_66) || defined(CONFIG_CLK_800_133_66) /* FIN 12MHz, Fout 800MHz */
#define APLL_MDIV400
#define APLL_PDIV3
#define APLL_SDIV1
#define CONFIG_SYNC_MODE
#elif defined(CONFIG_CLK_400_100_50) /* FIN 12MHz, Fout 400MHz */
#define APLL_MDIV400
#define APLL_PDIV3
#define APLL_SDIV2
#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_MDIV266
#define APLL_PDIV3
#define APLL_SDIV1
#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。
下面的源码下篇再分析:
#ifdefCONFIG_SYNC_MODE
ldrr1, [r0, #OTHERS_OFFSET]
movr2, #0x40
orrr1, r1, r2
strr1, [r0, #OTHERS_OFFSET]
nop
nop
nop
nop
nop
ldrr2, =0x80
orrr1, r1, r2
strr1, [r0, #OTHERS_OFFSET]
check_syncack:
ldrr1, [r0, #OTHERS_OFFSET]
ldrr2, =0xf00
andr1, r1, r2
cmpr1, #0xf00
bnecheck_syncack
#else/* ASYNC Mode */
nop
nop
nop
nop
nop
ldrr1, [r0, #OTHERS_OFFSET]
bicr1, r1, #0xC0
orrr1, r1, #0x40
strr1, [r0, #OTHERS_OFFSET]
wait_for_async:
ldrr1, [r0, #OTHERS_OFFSET]
andr1, r1, #0xf00
cmpr1, #0x0
bnewait_for_async
ldrr1, [r0, #OTHERS_OFFSET]
bicr1, r1, #0x40
strr1, [r0, #OTHERS_OFFSET]
#endif
movr1, #0xff00
orrr1, r1, #0xff
strr1, [r0, #APLL_LOCK_OFFSET]
strr1, [r0, #MPLL_LOCK_OFFSET]
strr1, [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]
bicr1, r1, #0x70000
orrr1, r1, #0x30000
strr1, [r0, #CLK_DIV2_OFFSET]
#endif
ldr r1, [r0, #CLK_DIV0_OFFSET]/*Set Clock Divider*/
bicr1, r1, #0x30000
bicr1, r1, #0xff00
bicr1, r1, #0xff
ldrr2, =CLK_DIV_VAL
orrr1, r1, r2
strr1, [r0, #CLK_DIV0_OFFSET]
ldrr1, =APLL_VAL
strr1, [r0, #APLL_CON_OFFSET]
ldrr1, =MPLL_VAL
strr1, [r0, #MPLL_CON_OFFSET]
ldrr1, =0x80200203/* FOUT of EPLL is 96MHz */
strr1, [r0, #EPLL_CON0_OFFSET]
ldrr1, =0x0
strr1, [r0, #EPLL_CON1_OFFSET]
ldrr1, [r0, #CLK_SRC_OFFSET]/* APLL, MPLL, EPLL select to Fout */
#if defined(CONFIG_CLKSRC_CLKUART)
ldrr2, =0x2007
#else
ldrr2, =0x7
#endif
orrr1, r1, r2
strr1, [r0, #CLK_SRC_OFFSET]
/* wait at least 200us to stablize all clock */
movr1, #0x10000
1:subsr1, r1, #1
bne1b
#if 0
mrcp15, 0, r0, c1, c0, 0
orrr0, r0, #0xc0000000/* clock setting in MMU */
mcrp15, 0, r0, c1, c0, 0
#endif
#ifdef CONFIG_SYNC_MODE/* Synchronization for VIC port */
ldrr1, [r0, #OTHERS_OFFSET]
orrr1, r1, #0x20
strr1, [r0, #OTHERS_OFFSET]
#else
ldrr1, [r0, #OTHERS_OFFSET]
bicr1, r1, #0x20
strr1, [r0, #OTHERS_OFFSET]
#endif
movpc, lr