【OK210试用体验】+ 《uboot源码之系统时钟配置》 - 在线问答 - 电子技术论坛 - 最好最受欢迎电子论坛!

【OK210试用体验】+ 《uboot源码之系统时钟配置》

mrbushy ( 楼主 ) 2015-9-6 21:04:21  只看该作者 倒序浏览
本帖最后由 mrbushy 于 2015-9-10 19:10 编辑

  查看芯片手册364页如下:




P521页



  可见时钟的配置主要分为四步:

(1)配置PLL  /* Set Clock divider */
(2)设置系统PLL锁定时间     /* Set Lock time */
(3)配置各模块分频系数PLL (MPS value)
(4)切换到PLL时钟 /* Set Source Clock */先把boardsamsungOK210lowlevel_init.S代码贴出来分析
  1. system_clock_init:

  2.         ldr        r0, =ELFIN_CLOCK_POWER_BASE        @0xe0100000

  3.         /* Set Mux to FIN */
  4.         ldr        r1, =0x0
  5.         str        r1, [r0, #CLK_SRC0_OFFSET]

  6.         ldr        r1,        =APLL_LOCKTIME_VAL
  7.         str        r1,        [r0, #APLL_LOCK_OFFSET]

  8.         /* Disable PLL */
  9.         ldr        r1, =0x0
  10.         str        r1, [r0, #APLL_CON0_OFFSET]
  11.         ldr        r1, =0x0
  12.         str        r1, [r0, #MPLL_CON_OFFSET]

  13.         ldr        r1, =0x0
  14.         str        r1, [r0, #MPLL_CON_OFFSET]

  15.         ldr           r1, [r0, #CLK_DIV0_OFFSET]
  16.         ldr        r2, =CLK_DIV0_MASK
  17.         bic        r1, r1, r2

  18.         ldr        r2, =CLK_DIV0_VAL
  19.         orr        r1, r1, r2
  20.         str        r1, [r0, #CLK_DIV0_OFFSET]

  21.         ldr        r1, =APLL_VAL
  22.         str        r1, [r0, #APLL_CON0_OFFSET]

  23.         ldr        r1, =MPLL_VAL
  24.         str        r1, [r0, #MPLL_CON_OFFSET]

  25.         ldr        r1, =VPLL_VAL
  26.         str        r1, [r0, #VPLL_CON_OFFSET]
  27. #if defined(CONFIG_EVT1)
  28.         ldr        r1, =AFC_ON
  29.         str        r1, [r0, #APLL_CON1_OFFSET]
  30. #endif
  31.         mov        r1, #0x10000
  32. 1:        subs        r1, r1, #1
  33.         bne        1b

  34.         ldr        r1, [r0, #CLK_SRC0_OFFSET]
  35.         ldr        r2, =0x10001111          @0x 10001111=10000000000000001000100010001
  36.         orr        r1, r1, r2
  37.         str        r1, [r0, #CLK_SRC0_OFFSET]

  38. #if defined(CONFIG_MCP_AC)

  39.         /* CLK_SRC6[25:24] -> OneDRAM clock sel = MPLL */
  40.         ldr        r1, [r0, #CLK_SRC6_OFFSET]
  41.         bic        r1, r1, #(0x3<<24)
  42.         orr        r1, r1, #0x01000000
  43.         str        r1, [r0, #CLK_SRC6_OFFSET]

  44.         /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
  45.         ldr        r1, [r0, #CLK_DIV6_OFFSET]
  46.         bic        r1, r1, #(0xF<<28)
  47.         bic        r1, r1, #(0x7<<12)        @; ONENAND_RATIO: 0
  48.         orr        r1, r1, #0x30000000
  49.         str        r1, [r0, #CLK_DIV6_OFFSET]

  50. #elif defined (CONFIG_MCP_H)

  51.         /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
  52.         ldr        r1, [r0, #CLK_SRC6_OFFSET]
  53.         bic        r1, r1, #(0x3<<24)
  54.         orr        r1, r1, #0x00000000
  55.         str        r1, [r0, #CLK_SRC6_OFFSET]

  56.         /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
  57.         ldr        r1, [r0, #CLK_DIV6_OFFSET]
  58.         bic        r1, r1, #(0xF<<28)
  59.         bic        r1, r1, #(0x7<<12)        @; ONENAND_RATIO: 0
  60.         orr        r1, r1, #0x00000000
  61.         str        r1, [r0, #CLK_DIV6_OFFSET]

  62. #elif defined (CONFIG_MCP_B) || defined (CONFIG_MCP_D)

  63.         /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
  64.         ldr        r1, [r0, #CLK_SRC6_OFFSET]
  65.         bic        r1, r1, #(0x3<<24)
  66.         orr        r1, r1, #0x01000000
  67.         str        r1, [r0, #CLK_SRC6_OFFSET]

  68.         /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
  69.         ldr        r1, [r0, #CLK_DIV6_OFFSET]
  70.         bic        r1, r1, #(0xF<<28)
  71.         bic        r1, r1, #(0x7<<12)        @; ONENAND_RATIO: 0
  72.         orr        r1, r1, #0x30000000
  73.         str        r1, [r0, #CLK_DIV6_OFFSET]

  74. #elif defined (CONFIG_MCP_SINGLE)

  75.         /* CLK_DIV6 */
  76.         ldr        r1, [r0, #CLK_DIV6_OFFSET]
  77.         bic        r1, r1, #(0x7<<12)        @; ONENAND_RATIO: 0
  78.         str        r1, [r0, #CLK_DIV6_OFFSET]

  79. #endif

  80.         mov        pc, lr
复制代码
  1. /* Clock & Power Controller for s5pc110*/
  2. #define APLL_LOCK_OFFSET                0x00
  3. #define MPLL_LOCK_OFFSET                0x08
  4. #define EPLL_LOCK_OFFSET                0x10
  5. #define VPLL_LOCK_OFFSET                0x20
  6. #define APLL_CON0_OFFSET                0x100
  7. #define APLL_CON1_OFFSET                0x104
  8. #define MPLL_CON_OFFSET                        0x108
  9. #define EPLL_CON_OFFSET                        0x110
  10. #define VPLL_CON_OFFSET                        0x120

  11. #define CLK_SRC0_OFFSET                        0x200
  12. #define CLK_SRC1_OFFSET                        0x204
  13. #define CLK_SRC2_OFFSET                        0x208
  14. #define CLK_SRC3_OFFSET                        0x20c
  15. #define CLK_SRC4_OFFSET                        0x210
  16. #define CLK_SRC5_OFFSET                        0x214
  17. #define CLK_SRC6_OFFSET                        0x218
  18. #define CLK_SRC_MASK0_OFFSET                0x280
  19. #define CLK_SRC_MASK1_OFFSET                0x284

  20. #define CLK_DIV0_OFFSET                        0x300
  21. #define CLK_DIV1_OFFSET                        0x304
  22. #define CLK_DIV2_OFFSET                        0x308
  23. #define CLK_DIV3_OFFSET                        0x30c
  24. #define CLK_DIV4_OFFSET                        0x310
  25. #define CLK_DIV5_OFFSET                        0x314
  26. #define CLK_DIV6_OFFSET                        0x318
  27. #define CLK_DIV7_OFFSET                        0x31c

  28. #define CLK_GATE_IP0_OFFSET                0x460
  29. #define CLK_GATE_IP1_OFFSET                0x464
  30. #define CLK_GATE_IP2_OFFSET                0x468
  31. #define CLK_GATE_IP3_OFFSET                0x46c
  32. #define CLK_GATE_IP4_OFFSET                0x470
  33. #define CLK_GATE_BLOCK_OFFSET                0x480

  34. #define CLK_OUT_OFFSET                        0x500
  35. #define CLK_DIV_STAT0_OFFSET                0x1000
  36. #define CLK_DIV_STAT1_OFFSET                0x1004
  37. #define CLK_MUX_STAT0_OFFSET                0x1100
  38. #define CLK_MUX_STAT1_OFFSET                0x1104
  39. #define SW_RST_OFFSET                        0x2000
复制代码

查看手册,P371页,找到PLL CONTROL REGISTERS。

3.7.2 PLL CONTROL REGISTERS
3.7.2.1 PLL Control Registers (APLL_LOCK / MPLL_LOCK / EPLL_LOCK / VPLL_LOCK)
•  (APLL_LOCK, R/W, Address = 0xE010_0000)
•  (MPLL_LOCK, R/W, Address = 0xE010_0008)
•  (EPLL_LOCK, R/W, Address = 0xE010_0010)
•  (VPLL_LOCK, R/W, Address = 0xE010_0020)

查看芯片手册371页



可知
APLL的锁时间为:24*30=720    --0x2D0
MPLL的锁时间为:24*200=4800  --0x12C0
EPLL的锁时间为:24*375=9000  --0x2328
VPLL的锁时间为:24*100=2400  --0x960
看程序前几句
1.设置locktime
  /* Set Mux to FIN */
        ldr        r1, =0x0
        str        r1, [r0, #CLK_SRC0_OFFSET]     /配置选择时钟源寄存器地址#define CLK_SRC0_OFFSET                         Clock Source Control Registers (CLK_SRC0, R/W, Address = 0xE010_0200)

        ldr        r1,        =APLL_LOCKTIME_VAL        
        str        r1,        [r0, #APLL_LOCK_OFFSET]     /在u-boot-2011.06-2013-05-30includeconfigsOK210.h中有定义#define APLL_LOCKTIME_VAL        0x2cf  即APLL的锁时间为719

这两句是设置apll-lock time

ldr    r1, [r0, #CLK_DIV0_OFFSET]      *取DIV0值
ldr r2, =CLK_DIV0_MASK
bic r1, r1, r2                          *清零

ldr r2, =CLK_DIV0_VAL
orr r1, r1, r2
str r1, [r0, #CLK_DIV0_OFFSET]          *写入DIV0值


2.倍频APLL


我们只要把P=3 M=125,S=1即可让输出频率为1000MHz,即MSOUT_MSYS=1000MHz
查看手册,在P372页找到APLL_CON0(0xE010_0100)。




代码:
     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]
#endif
mov r1, #0x10000
1: subs r1, r1, #1                      *耗时等待稳定
bne 1b


u-boot-2011.06-2013-05-30includeconfigsOK210.h中查得
#define set_pll(mdiv, pdiv, sdiv)        (1<<31 | mdiv<<16 | pdiv<<8 | sdiv)

#define APLL_VAL        set_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)
#define MPLL_VAL        set_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)
#define EPLL_VAL        set_pll(EPLL_MDIV,EPLL_PDIV,EPLL_SDIV)
#define VPLL_VAL        set_pll(VPLL_MDIV,VPLL_PDIV,VPLL_SDIV)



if defined(CONFIG_CLK_667_166_166_133)
#define APLL_MDIV       0xfa
#define APLL_PDIV       0x6
#define APLL_SDIV       0x1
#elif defined(CONFIG_CLK_533_133_100_100)
#define APLL_MDIV       0x215
#define APLL_PDIV       0x18
#define APLL_SDIV       0x1
#elif defined(CONFIG_CLK_800_200_166_133) ||
        defined(CONFIG_CLK_800_100_166_133) ||
        defined(CONFIG_CLK_400_200_166_133) ||
        defined(CONFIG_CLK_400_100_166_133)
#define APLL_MDIV       0x64
#define APLL_PDIV       0x3
#define APLL_SDIV       0x1
#elif defined(CONFIG_CLK_1000_200_166_133)
#define APLL_MDIV       0x7d
#define APLL_PDIV       0x3
#define APLL_SDIV       0x1
#endif

#define APLL_LOCKTIME_VAL        0x2cf
)



#if defined(CONFIG_CLK_533_133_100_100)
#define MPLL_MDIV        0x190
#define MPLL_PDIV        0x6
#define MPLL_SDIV        0x2
#else
#define MPLL_MDIV        0x29b
#define MPLL_PDIV        0xc
#define MPLL_SDIV        0x1
#endif

(
#define EPLL_MDIV        0x60
#define EPLL_PDIV        0x6
#define EPLL_SDIV        0x2

#define VPLL_MDIV        0x6c
#define VPLL_PDIV        0x6
#define VPLL_SDIV        0x3


)








这里设置系统时钟apll为1000Mhz所以APLL_MDIV       0x7d  (125)   
APLL_PDIV       0x3      
APLL_SDIV       0x1

mpll为667Mhz 所以
MPLL_MDIV        0x29b(667)      



MPLL_PDIV        0xc   (12)        


MPLL_SDIV        0x1





同理设置epll为80Mhz  
EPLL_MDIV        0x60  (根据数据手册这里0x60应该改为0x50即80)       EPLL_PDIV        0x6 (应改为0x3)      EPLL_SDIV        0x2(改为0x3)


vpll为54Mhz
VPLL_MDIV        0x6c    (108)    VPLL_PDIV        0x6    VPLL_SDIV        0x3


参考芯片手册P361页时钟生成电路图,系统的MSYS/DSYS/PSYS的CLK全部来自于APLL和MPLL,现在开始对APLL/MPLL进行分频,分给不同的设备,如Cotrex A8内核或其它设备。在分频之前,必须要先选择时钟。




3.选择时钟源查看芯片手册378页


参考芯片手册P361页时钟生成电路图,以APLL以例,查找FOUTAPLL和FINPLL




由图所知,FINPLL是没有倍频的频率,我们要选的是倍频后的,所以应该选择FOUTAPLL,依此类推,后面几位选上FOUTMPLL/FOUTEPLL/FOUTVPLL。那第[28]位,ONENADN选择什么呢?往上查一下ONENAND用的是什么CLK,在P363页查找到用的是PSYS,所以这里应该选择0。



ldr        r1, [r0, #CLK_SRC0_OFFSET]
        ldr        r2, =0x10001111          @/0x 10001111=10000000000000001000100010001即ldr    r2, =(0<<28|1<<12 |1<<8 |1<<4 |1<<0) 如此配置完时钟源寄存器Clock Source Control Registers (CLK_SRC0, R/W, Address = 0xE010_0200)后就完成了时钟源选择/
        orr        r1, r1, r2
        str        r1, [r0, #CLK_SRC0_OFFSET]



4.分频
查看P387页,系统时钟分频操作的寄存器是CLK_DIV0,Address = 0xE010_0300

回过头去,再去看时钟频率的产生图,最终MSYS有五个CLK,ARMCLK/HCLK_MSYS/PCLK_MSYS/HCLK_IMEM/SCLK_DMC0



P356查看常用CLK
Values for the high-performance operation:
•  freq(ARMCLK)   = 1000 MHz
•  freq(HCLK_MSYS)   = 200 MHz
•  freq(HCLK_IMEM)   = 100 MHz
•  freq(PCLK_MSYS)   = 100 MHz
•  freq(HCLK_DSYS)   = 166 MHz
•  freq(PCLK_DSYS)   = 83 MHz
•  freq(HCLK_PSYS)   = 133 MHz
•  freq(PCLK_PSYS)   = 66 MHz
•  freq(SCLK_ONENAND)    = 133 MHz, 166
在数据手册387页寄存器CLK_DIV0的表格上还有这样一段话:








面列表中CLK也整理一下,列表出来:
•  freq(SCLKAPLL)   = 1000 MHz
•  freq(SCLKMPLL)   = 667 MHz
•  freq(SCLKA2M)   = 400 MHz
由飞凌提供的uboot 在串口打印信息可知各时钟频率确实按如上分析配置

[    0.000000] S5PV210: PLL settings, A=1000000000, M=667000000, E=80000000 V=54000000
[    0.000000] S5PV210: ARMCLK=1000000000, HCLKM=200000000, HCLKD=166750000
[    0.000000] HCLKP=133400000, PCLKM=100000000, PCLKD=83375000, PCLKP=66700000
[    0.000000] sclk_dmc: source is sclk_a2m (0), rate is 200000000
CPU:  S5PV210@1000MHz(OK)
   APLL = 1000MHz, HclkMsys = 200MHz, PclkMsys = 100MHz
   MPLL = 667MHz, EPLL = 80MHz
   HclkDsys = 166MHz, PclkDsys = 83MHz
   HclkPsys = 133MHz, PclkPsys = 66MHz
   SCLKA2M  = 200MHz
Serial = CLKUART
Board:   SMDKV210
下面一位一位的开始分析寄存器是CLK_DIV0:
[2:0]ARMCLK = 1000MHz,MOUT_MSYS = 2000MHz,ARMCLK = MOUT_MSYS/(1+1),APLL_RATIO为1,1<<0
[6:4]SCLKA2M = 400MHz,SCLKAPLL = 1000MHz,由于无法整除,而SCLKA2M最大为400,我们只要保证不超过就行,可以低一些,SCLKA2M = SCLKAPLL / (a+ 1)  = 333  a>=2,a<<4
[10:8]HCLK_MSYS = 200MHz,ARMCLK = 1000MHz,HCLK_MSYS = ARMCLK /(4 + 1),HCLK_MSYS_RATIO为4,4<<8
[14:12]PCLK_MSYS = 100MHz,HCLK_MSYS = 200MHz,PCLK_MSYS = HCLK_MSYS / (1 + 1) ,PCLK_MSYS_RATIO为1,1<<12  
[19:16]HCLK_DSYS = 166MHz,MOUT_DSYS = 667MHz,HCLK_DSYS = MOUT_DSYS / (3+ 1) ,HCLK_DSYS_RATIO为1,3<<16
[22:20]PCLK_DSYS = 83MHz,HCLK_DSYS = 166MHz,PCLK_DSYS = HCLK_DSYS / (1 + 1) ,PCLK_DSYS_RATIO为1,1<<20
[27:24]HCLK_PSYS = 133MHz,MOUT_PSYS = 667MHz,HCLK_PSYS = MOUT_PSYS / (4 + 1) ,HCLK_PSYS_RATIO为1,4<<24
[30:28]PCLK_PSYS = 66MHz,HCLK_PSYS = 133MHz,PCLK_PSYS = HCLK_PSYS / (1 + 1) ,PCLK_PSYS_RATIO为1,1<<28



代码为
:    ldr           r1, [r0, #CLK_DIV0_OFFSET]   
        ldr        r2, =CLK_DIV0_MASK   //#define CLK_DIV0_MASK        0x7fffffff=1111111111111111111111111111111
        bic        r1, r1, r2   //*将CLK_DIV0中有关分频的位全部清零0~30*/

        ldr        r2, =CLK_DIV0_VAL   /ldr    r2, =(0<<0)|(2<<4)|(4<<8)|(1<<12)|(3<<16)|(1<<20)|(4<<24)|(1<<28)
        orr        r1, r1, r2
        str        r1, [r0, #CLK_DIV0_OFFSET]
u-boot-2011.06-2013-05-30includeconfigsOK210.h中查得


#define CLK_DIV0_MASK        0x7fffffff
#if 0
//#define CONFIG_CLK_667_166_166_133
//#define CONFIG_CLK_533_133_100_100
//#define CONFIG_CLK_800_200_166_133
//#define CONFIG_CLK_800_100_166_133
#endif
#define CONFIG_CLK_1000_200_166_133


#elif defined(CONFIG_CLK_1000_200_166_133)
#define CLK_DIV0_VAL    ((0<
                        |(3<
#endif



最后一段程序是对其他时钟的配置只有CONFIG_MCP_SINGLE有定义
#if defined(CONFIG_MCP_AC)

        /* CLK_SRC6[25:24] -> OneDRAM clock sel = MPLL */
        ldr        r1, [r0, #CLK_SRC6_OFFSET]
        bic        r1, r1, #(0x3<<24)
        orr        r1, r1, #0x01000000
        str        r1, [r0, #CLK_SRC6_OFFSET]

        /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
        ldr        r1, [r0, #CLK_DIV6_OFFSET]
        bic        r1, r1, #(0xF<<28)
        bic        r1, r1, #(0x7<<12)        @; ONENAND_RATIO: 0
        orr        r1, r1, #0x30000000
        str        r1, [r0, #CLK_DIV6_OFFSET]

#elif defined (CONFIG_MCP_H)

        /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
        ldr        r1, [r0, #CLK_SRC6_OFFSET]
        bic        r1, r1, #(0x3<<24)
        orr        r1, r1, #0x00000000
        str        r1, [r0, #CLK_SRC6_OFFSET]

        /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
        ldr        r1, [r0, #CLK_DIV6_OFFSET]
        bic        r1, r1, #(0xF<<28)
        bic        r1, r1, #(0x7<<12)        @; ONENAND_RATIO: 0
        orr        r1, r1, #0x00000000
        str        r1, [r0, #CLK_DIV6_OFFSET]

#elif defined (CONFIG_MCP_B) || defined (CONFIG_MCP_D)

        /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
        ldr        r1, [r0, #CLK_SRC6_OFFSET]
        bic        r1, r1, #(0x3<<24)
        orr        r1, r1, #0x01000000
        str        r1, [r0, #CLK_SRC6_OFFSET]

        /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
        ldr        r1, [r0, #CLK_DIV6_OFFSET]
        bic        r1, r1, #(0xF<<28)
        bic        r1, r1, #(0x7<<12)        @; ONENAND_RATIO: 0
        orr        r1, r1, #0x30000000
        str        r1, [r0, #CLK_DIV6_OFFSET]

#elif defined (CONFIG_MCP_SINGLE)

        /* CLK_DIV6 */
        ldr        r1, [r0, #CLK_DIV6_OFFSET]
        bic        r1, r1, #(0x7<<12)        @; ONENAND_RATIO: 0
        str        r1, [r0, #CLK_DIV6_OFFSET]

#endif

   最后     mov        pc, lr  /返回指针


ok,时钟配置代码分析结束
下一篇《NANDFLAH原理分析》



   

boot sequence.2_proc.jpg (36.97 KB, 下载次数: 11)

boot sequence.2_proc.jpg

2.png (153.48 KB, 下载次数: 7)

2.png

5.png (11.28 KB, 下载次数: 10)

5.png

1个回复

mrbushy 发表于 2015-9-13 12:37:57
加油!!!!!!
回复

举报 使用道具

您需要登录后才可以回帖 登录 | 注册

本版积分规则


关闭

站长推荐上一条 /6 下一条

小黑屋|手机版|Archiver|电子发烧友 ( 湘ICP备2023018690号 )

GMT+8, 2024-11-21 19:46 , Processed in 0.773441 second(s), Total 62, Slave 42 queries .

Powered by 电子发烧友网

© 2015 bbs.elecfans.com

微信扫描
快速回复 返回顶部 返回列表