Chinaunix首页 | 论坛 | 博客
  • 博客访问: 251548
  • 博文数量: 81
  • 博客积分: 325
  • 博客等级: 一等列兵
  • 技术积分: 595
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-17 21:00
文章分类
文章存档

2016年(2)

2013年(33)

2012年(47)

我的朋友

分类:

2012-12-05 20:18:20

原文地址:ok6410 作者:dglwx

1,修改OK6410的CPU主频

s3c2410处理器系统时钟包括FCLK,HCLK和PCLK,它们一起由MPLL分频提供。

FCLK:CPU时钟,就是处理器的主频。常说的s3c2410A能上200MHz,s3c2440A能上400MHz就是指它。它为ARM920T输入。

HCLK:为AHB总线外围时钟,为ARM920T、内存控制器、中断控制器、LCD控制器、DMA和USB Host输入。

PCLK:为APB总线外围时钟,为WDT,I2S,I2C,PWMtimer,MMC接口,ADC,UART,GPIO,RTC和SPI等片内外围设备输入。

当Main PLL锁定之后,FCLK=Mpll,而HCLK,PCLK分别由HDIVN,PDIVN确定是否由FCLK分频。

 锁相环是用来产生时钟频率的,s3c2440有两个锁相环:MPLL和UPLL。
MPLL是用来产生FCLK,HCLK,PCLK三种时钟频率的,FCLK是CPU的时钟信号,HCLK是AHB总线的时钟信号,PCLK是APB总线的时钟信号。UPLL则是用于产生USB的时钟。下面主要讲述FCLK,HCLK,PCLK时钟频率的获得。

通过设置MPLL锁相环就可以得到CPU的时钟信号FCLK,而MPLL的值依赖于mdiv,pdiv,sdiv的值
void ChangeMPllValue(int mdiv,int pdiv,int sdiv)
{
    rMPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
}

CPU时钟信号FCLK的频率计算公式为:
FCLK=(2*m*FIN)/(p*2^s)
其中 m=(mdiv+8), p=(pdiv+2), s=sdiv,

FIN为输入时钟的频率,通过设置OM[3:2]来选择是用外部晶振还是外部时钟。要获得HCLK和PCLK的值,则还需设置分频器,即CLKDIVN寄存器。

若设置为[2:1]=01,[0]=1,则FCLK:HCLK:PCLK的分频系数之比为1:2:4,即FCLK,HCLK,PCLK的频率为:FCLK,FCLK/2,FCLK/4。

例:
MPLLCON:设为(0x5c << 12)|(0x04 << 4)|(0x00),即0x5c040
对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV。
根据计算公式:
FCLK = (2*m * Fin)/(p * 2^s)

其中: m = MDIV + 8 = 92+8 = 100 , p = PDIV + 2 = 4+2 = 6, s = 0,Fin=12MHz(无源晶振频率12MHz)。
则FCLK= (2*100*12)/(6*2^0) = 400 MHz
若设置分频器CLKDIVN的[2:1]=01,[0]=1,则HCLK=200MHz,PCLK=100MHz。


 在Linux中没有设置S3C6410的CPU时钟,而是在u-boot(uboot1.1.6/include/configs/smdk6410.h)中设置好的:
//#define CONFIG_CLK_800_133_66
//#define CONFIG_CLK_666_133_66
//#define CONFIG_CLK_532_133_66
#define CONFIG_CLK_400_133_66
//#define CONFIG_CLK_400_100_50
//#define CONFIG_CLK_OTHERS

  在Linux的时钟频率代码(linux2.6.28/arch/arm/plat-s3c64xx/s3c6400-clock.c)中也只是直接从PLL寄存器中读取:
void __init_or_cpufreq s3c6400_setup_clocks(void)
{
   ***
   xtal = clk_get_rate(xtal_clk);
    clk_put(xtal_clk);

    printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);

    epll = s3c6400_get_epll(xtal);
    mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
    apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));

    fclk = apll / GET_DIV(clkdiv0, S3C6410_CLKDIV0_ARM);

    printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
           apll, mpll, epll);

    if(__raw_readl(S3C_OTHERS) & S3C_OTHERS_SYNCMUXSEL_SYNC) {
        /* Synchronous mode */
        hclkx2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
    } else {
        /* Asynchronous mode */
        hclkx2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
    }

    hclk = hclkx2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
    pclk = hclkx2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);

    printk(KERN_INFO "S3C64XX: HCLKx2=%ld, HCLK=%ld, PCLK=%ld\n", hclkx2, hclk, pclk);
}

   S3C6410 nandflash的分区表:arch/arm/plat-s3c/include/plat/partition.h
阅读(705) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~