s3c6410的时钟初始化

一篇不可多得的有关时钟方面的博文:

http://www.cnblogs.com/lp1129/articles/3008344.html

1. PHASE LOCKED LOOP(PLL)

S3C6410有三个PLL,分别为APLL、MPLL、EPLL,通过设置它们将输入时钟同步输出达到操作CPU的工作频率,如图1-1描述了时钟产生逻辑单元

图1-1 时钟产生逻辑单元

APLL产生ACLK,为ARM core提供工作时钟

MPLL产生HCLKX2、HCLK和PCLK,用于AXI、AHB和APB总线时钟

EPLL为特殊外设,如UART、USB、IIS、IIC等提供工作时钟

ARM core的时钟手册上标明最大为667MHz,实际使用时跑800MHz基本没有问题

HCLKX2主要提供时钟给DDR使用,最大可以到266MHz

HCLK可以看做AXI\AHB总线时钟,APB可以看做APB总线时钟

Voltage Controlled Oscillator (VCO)P[5:0]位来设置FIN进行分频。通过设置Main-Divider分频数,分频压控振荡器产生的输出时钟频率,分频之后的低频进入鉴相器ScalerS[2:0]位设置PLL的输出时钟频率都可以通过

CLK_SRC寄存器的低三位CLK_SRC[2:0]分别控制三种工作时钟。当对应位被置位,则产生对应PLL的工作时钟。否则,不会产生对应的PLL工作时钟。

2. 三种工作时钟的产生

ARM1176最高产生667Mhz的工作频率。用户可以通过设置内部时钟分频器的值来控制输出工作时钟,而不用修改PLL的工作频率。分频器可以选择1~16的分频数。ARM内核可以通过修改分频器的值来减少系统电源的损耗。

S3C6410内部含有AXI,AHB和APB总线,通过不同的总线控制不同的外设,关闭总线上的时钟频率可以达到系统节能的目的。AXI,AHB总线最高工作在133MHz频率下,APB总线最高工作在66MHz频率下。由于APB和AXI,AHB总线上二者工作频率不一致,在这两种总线上进行数据同步传输时会采用特殊逻辑单元,如图1-2所示。

图1-2 系统总线工作频率设置

HCLKX2时钟由DDR0,DDR1两个DDR控制器产生,其最高可以以266MHz频率发送和接收数据。每个HCLKX2时钟可以根据用户需要分别被关闭掉来减少系统损耗。AHB总线上的时钟由DIV(HCLK)分频器分频后输出,同样AHB总线上的外设也可以被关闭掉以节省电源消耗。HCLK_GATE寄存器用来关闭工作在HCLKX2和HCLK时钟上的外设。

慢速设备连接在APB总线上。APB时钟最高工作在66MHz,通过DIV(PCLk)分频器来进行分频设置,通过设置PCLK_GATE寄存器来关闭对应的APB总线上的外设。根据S3C6410硬件手册说明,AHB总线和APB总线上的频率必须是偶数,例如,如果DIV(HCLK)对应控制位CLK_DIV[8]设置为1,则DIV(PCLK)对应位CLK_DIV0[15:12]必须设置为1,3,5,…等奇数。否则,APB总线上的外设不能正解的进行数据传输。

AHB总线上的JPEG和安全相关子系统不能工作在133MHz,AHB总线专门为这样低频子系统提供低频工作时钟,通过设置DIV(CLKJPEG)和DIV(CLKSECUR)分频位来设置其工作频率。因此,同样在APB总线上也有类似的这种限制设定,DIV(CLKJPEG)和DIV(CLKSECUR)对应的CLK_DIV0[27:24]分频位和CLK_DIV0[19:18]分频位必须是奇数,二者的和是偶数。如表1-1所示,官方给出了推荐的设置参数。

表1-1 官方推荐参数

3. MFC模块时钟的产生

MFC模块需要特殊的时钟,如图1-3所示。

图1-3 MFC时钟产生逻辑

MFC时钟源可以从HCLKX2和MOUT(EPLL)中选择。MFC的工作时钟使用HCLKX2来分频。默认HCLKX2时钟频率为266MHz。因此,CLK_DIV0[31:28]必须设置为b0001来产生MFC工作的133MH时钟。当MFC模块不需要工作在高性能模式下时,有两种方式可以减少MFC模块工作频率来达到减少MFC模块的功耗。第一种方式是设置CLK_SRC[4]使用EPLL的输出时钟,另外一种方式是设置CLK_DIV0[31:28]的分频数,同时,设置CLK_SRC[4]位,这样低频工作时钟就可以提供给MFC模块。EPLL输出时钟是与HCLKX2和HCLK独立的。

4. UART、SPI、MMC 工作时钟的产生

如图1-4所示,是UART、SPI、MMC三种外设工作时钟逻辑

图1-4 UART,SPI,MMC工作时钟逻辑模块

通过设置CLK_DIV2[19:16]位来设置UART的工作频率的分频数,通过SCLK_GATE[9]来开启关闭UART时钟源。

该模块中有一个额外的时钟源CLK27M,使用该时钟源可以提供更多的可选工作时钟。

5. 时钟的开启/关闭控制

HCLK_GATE,PCLK_GATE和SCLK_GATE用来控制三种时钟源的产生,如果对应的位被设置,对应时钟就会产生。

HCLK_GATE控制HCLK总线上的外设工作时钟的产生,PCLK_GATE控制PCLK总线上的外设工作时钟的产生,PCLK总线上的外设需要特定的时钟,它们通过SCLK_GATE来设置。

6. 同步667MH操作模式

根据S3C6410硬件手册,ARMCLK和HCLK的时钟比必须是整数,用来同步ARM内核和AXI总线接口二者的时钟。S3C6410没有对CPU工作在533MHz做限制,ARMCLK = 533MHz,HCLKX2=266MHz,HCLK=133MH,不过,对于工作在533MHz以上时,例如667Mhz时,只能支持1:2.5:5的时钟比(ARMCLK = 667MHz,HCLKX2=266MHz,HCLK=133MH)

7. 时钟分频

图1-5时钟分频模块

如图1-5所示,时钟分频模块产生三种时钟,ARMCLK,HCLKX2,HCLK。时钟分频器包含两部分,预分频器组和后分频器组,预分频器包含一个1/2预分频器和1/5预分频器,这两个分频器是固定的不能被软件配置,而后分频器可以通过配置CLK_DIV0寄存器方式进行配置。当MISC_CON的SYNC667MHz位被设置时,两个预分频器同时工作,产生APLL的分频经过预分频器分频的时钟,如果APLL的FOUT输出频率为1.33GHz,预分频器ARMCLK的输出为667Mhz,预分频器HCLK的输出为266MHz。这样经过分频的时钟可以通过CLK_DIV0寄存器进行配置。

我们打算将ARM内核时钟设置为官方推荐的稳定的533MHz,让APLL为AHB,APB输出工作频率。让MPLL为UART等外设提供工作频率,EPLL不工作。同时设置HCLKX2为266MHz,HCLK为133MHz,PCLK为66.5MHz,UART工作时钟为66.5MHz。

1) 选择HCLKX2, HCLK, PCLK的时钟源,由图1-1可知其时钟源可以通过OTHER[6]选择是由DOUT_APLL还是MOUT_MPLL,我们选择从DOUT_APLL。

ldr   r0, =CLOCK_BASE                                ;0x7e00f000
ldr   r1, [r0, #OTHERS_OFFSET]               ; 选择MPLL的时钟源
movr2, #0x40
orr   r1, r1, r2
str    r1, [r0, #OTHERS_OFFSET]
nop
nop
nop
nop
; 选择CPU的同步工作模式
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
cmpr1, #0xf00
bne  check_syncack                

2) 设置变频锁定时间,当系统时钟修改之后要经过段LOCK时间

; 设置变频锁定时间
movr1, #0xff00
orr   r1, r1, #0xff
str   r1, [r0, #APLL_LOCK_OFFSET]
str   r1, [r0, #MPLL_LOCK_OFFSET]
str   r1, [r0, #EPLL_LOCK_OFFSET]

3) 设置ARMCLK、HCLKX2、 HCLK、 PCLK的分频

各种频率的关系如图1-2所述:

APLL或MPLL产生的输出频率经过OTHER[6]选择之后再经过MISC_CON[19]选择是否被1/5分频,产生的输出频率进入DIV_HCLKx2,根据CLK_DIV0的不同位设置HCLKX2,HCLK,PCLK,CLKJPEG,CLKSECUR的输出频率。其值设置情况如CLK_DIV0寄存器描述内容所述。

◈ 我们将MPLL选择DOUT_APLL,MISC_ON[19]不进行分频,DOUT_APLL产生的时钟(533MHz)直接进入到DIV_HCLKX2分频器中。

◈ 根据硬件手册可知,HCLKX2的频率固定为266MHz,所以HCLKX2_RATIO设置为0b1

◈ HCLK上挂接有内存,Mobile DDR内存最高工作在133MHz,所以HCLK最高主频设置为HCLKX2的1/2,即:HCLK_RATIO = 0b1

◈ 设置PCLK上的工作频率为66.5MHz,即:PCLK_RATIO = 0b11

◈ 设置ARM内核工作频率为553MHz,即:ARM_RATIO = 0b0

◈ 设置DOUT_MPLL为266MHz,为后面UART提供时钟源,即:MPLL_RATIO = 0b0

◈ 其它时钟频率保持默认值

; MPLL_RATIO = 0<<4, ARM_RATIO = 0
; DOUT_MPLL = MOUT_MPLL/(MPLL_RATIO + 1)
; 即 ARMCLK = DOUT_APLL / (ARM_RATIO + 1)
; 即 ARMCLK = 533MHz, DOUT_MPLL = 266MHz
; HCLKX2_RATIO = 1<<9 , HCLK_RATIO = 1<<8, PCLK_RATIO = 3<<12, HCLKX2IN = 533
; 即 HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) = 266
; 即 HCLK = HCLKX2 / (HCLK_RATIO + 1) = 133
; 即 PCLK = HCLKX2 / (PCLK_RATIO + 1) = 66.5
ldr r1, [r0, #CLK_DIV0_OFFSET]
bic   r1, r1, #0xff00
bic   r1, r1, #0xff
ldr   r2, =0x3300
orr   r1, r1, r2
str   r1, [r0, #CLK_DIV0_OFFSET]

4) 设置UART工作时钟

由图1-6可知,通过设置CLK_SRC[1]选择DOUT_MPLL的工作时钟是否进行倍频,通过设置CLK_DIV0[4]对时钟进行分频,再通过CLK_SRC[13]选择UART的工作时钟源,设置CLK_DIV2[19:16]位用于分频UART工作时钟。由前面可知DOUT_MPLL = 266MHz,UART选择其作为自己工作时钟源,则对其进行1/4分频可以得到66.5MHz。

如下表可知:设置寄存器CLK_DIV2[19:16] = 0b11,同时还要设置CLK_SRC[13] = 0b1即可。

; 设置UART串口的分频数寄存器CLK_DIV2
ldr r1, [r0, #CLK_DIV2_OFFSET]
bic   r1, r1, #0x70000
orr   r1, r1, #0x30000                ; 设置其值为3,即CLKUART = CLKUARTIN / 4
str   r1, [r0, #CLK_DIV2_OFFSET]

5) 使能APLL,EPLL锁相环

根据硬件手册上的说明设置APLL, EPLL的M、D、S分频数。

APLL产生533MHz的FOUT_APLL

EPLL产生266MHz的MOUT_EPLL

;使能APLL锁相环,配置M,D,S分频数, according to Datasheet FOUT_APLL = 533 then
; APLL_EN = 1<<31, MDIV = 266<<16, PDIV = 3<<8, SDIV = 1
ldr   r1, = 0x810a0301
str   r1, [r0, #APLL_CON_OFFSET]
; 使能MPLL锁相环,配置M,D,S分频数
; MPLL_EN = 1<<31, MDIV = 266<<16, PDIV = 3<<8, SDIV = 2
ldr   r1, = 0x810a0302
str   r1, [r0, #MPLL_CON_OFFSET]

6) 设置对应时钟源寄存器,为各种外设提供时钟频率

; UART_SEL = 0b1
; MPLL_SEL = 0b1, APLL_SEL = 0b1
 
ldr   r1, [r0, #CLK_SRC_OFFSET]
ldr   r2, =0x2005                                                   ; 同时设置UART的时钟源来自MPLL
orr   r1, r1, r2
str   r1, [r0, #CLK_SRC_OFFSET]

 

============================= 来看代码 ================================

6410的主时钟初始化是在u-boot中做的,linux中只是负责读取该数值。

1、u-boot-1.1.6/include/configs/smdk6410.h

APLL设置,这是666MHz的配置,可参考手册修改 
#define APLL_MDIV 333 
#define APLL_PDIV 3
#define APLL_SDIV 1

MPLL设置,我尝试修改,UART就没有输出了
/* fixed MPLL 533MHz */
#define MPLL_MDIV 266
#define MPLL_PDIV 3
#define MPLL_SDIV 1 

APLL分频因子
#define Startup_APLLdiv   0
MPLL到HCLKX2的分频因子
#define Startup_HCLKx2div 2
HCLKX2到PCLK的分频因子
#define Startup_PCLKdiv   3
HCLKX2到HCLK的分频因子
#define Startup_HCLKdiv   1
MPLL分频因子
#define Startup_MPLLdiv   1

#define CONFIG_SYNC_MODE
同步模式下,HCLK时钟由APLL分频而来

2、u-boot-1.1.6/board/samsung/smdk6410/lowlevel_init.s
来看看UART的时钟,UART的时钟由EXT_UCLK1提供,UCLK是MPLL的分频,不改MPLL,UART就不会乱

/*
* uart_asm_init: Initialize UART in asm mode, 115200bps fixed.
* void uart_asm_init(void)
*/
uart_asm_init:
/* set GPIO to enable UART */
@ GPIO setting for UART
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0x220022
str   r1, [r0, #GPACON_OFFSET]

ldr r1, =0x2222
str   r1, [r0, #GPBCON_OFFSET]

ldr r0, =ELFIN_UART_CONSOLE_BASE   @0x7F005000
mov r1, #0x0
str r1, [r0, #UFCON_OFFSET]
str r1, [r0, #UMCON_OFFSET]

mov r1, #0x3                @was 0.
str r1, [r0, #ULCON_OFFSET]

#if defined(CONFIG_CLKSRC_CLKUART)//UART的时钟由EXT_UCLK1提供
ldr r1, =0xe45    /* UARTCLK SRC = 11 => EXT_UCLK1*/
#else
ldr r1, =0x245    /* UARTCLK SRC = x0 => PCLK */
#endif
str r1, [r0, #UCON_OFFSET]
#if defined(CONFIG_UART_50)
ldr r1, =0x1A
#elif defined(CONFIG_UART_66) //EXT_UCLK1为66M时的分频参数
ldr r1, =0x22
#else
ldr r1, =0x1A
#endif
str r1, [r0, #UBRDIV_OFFSET]
#if defined(CONFIG_UART_50)
ldr r1, =0x3
#elif defined(CONFIG_UART_66)
ldr r1, =0x1FFF
#else
ldr r1, =0x3
#endif
str r1, [r0, #UDIVSLOT_OFFSET]
ldr r1, =0x4f4f4f4f
str r1, [r0, #UTXH_OFFSET]   @'O'
mov pc, lr

这是配主频的代码,没啥好说的

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, =0x80200103    /* 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 */

最后要注意一下同步模式:

内核和总线不同步时,需用异步模式。

我改变了系统主频,但没有改成异步模式,结果导致串口异常。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值