TQ2440的FCLK,HCLK,PCLK,UCLK时钟频率设置 (2013-08-22 09:14:19)转载▼

来源:互联网 发布:淘宝请叫我八戒姐姐 编辑:程序博客网 时间:2024/06/02 00:14


    S3C2440有两个PLL(phase lockedloop)一个是MPLL,一个是UPLL。MPLL用于CPU及其他外围器件,UPLL用于USB。用于产生FCLK, HCLK, PCLK三种频率,这三种频率分别有不同的用途:

 

FCLK是CPU提供的时钟信号。

HCLK是为AHB总线提供的时钟信号, Advanced High-performance Bus,主要用于高速外设,比如内存控制器,中断控制器,LCD控制器, DMA 等。

PCLK是提供给用于外设如WDT,IIS,I2C,PWM,MMC/SD,ADC,UART,GPIO,RTC,SPI的APB总线的时钟。

 

    从S3C2440的DATASHEET里可以看到,S3C2440最大支持400MHz的主频,但是这并不意味着一定工作在400MHz下面,可以通过设定MPLL, UPLL寄存器来设定CPU的工作频率。

    尽管在CPU上电(power-on)或者复位(reset)后,MPLL就开始进入工作状态,但是此时MPLL的输(Mpll)并不作为系统的时钟,而是直接使用外部信号EXTCLK或者外部时钟晶振作为系统时钟。直到软件初始化MPLL寄存器(rMPLLCON),写入了有效的值过后,系统才开始使用MPLL的输出(Mpll)作为系统时钟。虽然很多时候我们不必重新设置MPLL寄存器(rMPLLCON)新的值,但是为了使系统使用其输出作为时钟信号,在软件初始化系统部分,还是要向rMPLLCON写入一个有效的旧的值。这样子才使系统处于正确的工作状态。

 

TQ2440程序中FCLK=400MHz,MDIV=92=0x5C、PDIV=1、SDIV=1

 

#defineFIN  (12000000)

 

rMPLLCON=(92<<12)|(1<<4)|1;  //设置FCLK为400M

ChangeClockDivider(14,12);      //这个函数在2440lib.c中定义的,设置分频比为1:4:8

CalcBusClk();                 //计算总线频率

 

下面是被调用的两个函数

//************************[HCLK, PCLK ]***************************

voidChangeClockDivider(int hdivn_val,int pdivn_val)//两个参数分别为FCLK:HCLK,HCLK:PCLK的比值

{

 int hdivn=2, pdivn=0;

 

 // hdivn_val (FCLK:HCLK)ratio hdivn

 // 11          1:1       (0)

 // 12          1:2       (1)

 // 13          1:3       (3)

 // 14          1:4       (2)

 // pdivn_val (HCLK:PCLK)ratio pdivn

 // 11          1:1       (0)

 // 12          1:2       (1)

 switch(hdivn_val) {

  case 11: hdivn=0; break;

  case 12: hdivn=1; break;

  case 13:

  case 16: hdivn=3; break;

  case 14:

  case 18: hdivn=2; break;

 }

 

 switch(pdivn_val) {

  case 11: pdivn=0; break;

  case 12: pdivn=1; break;

 }

 

 //Uart_Printf("Clock division change[hdiv:%x, pdiv:%x]\n", hdivn, pdivn);

 rCLKDIVN = (hdivn<<1) | pdivn;

 switch(hdivn_val) {

  case 16: // when 1, HCLK=FCLK/8.

   rCAMDIVN = (rCAMDIVN & ~(3<<8)) |(1<<8);

  break;

  case 18: // when 1, HCLK=FCLK/6.

   rCAMDIVN = (rCAMDIVN & ~(3<<8)) |(1<<9);

  break;

 }

 

 if(hdivn!=0)

  MMU_SetAsyncBusMode();

 else

  MMU_SetFastBusMode();

}

voidCalcBusClk(void)    //计算总线频率

{

 U32 val,UPLL;

 U8 m, p, s;

 val = rMPLLCON;

 m = (val >> 12) & 0xff;

 p = (val >> 4) & 0x3f;

 s = val & 3;

 FCLK =((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;

 

 val = rCLKDIVN;

 m = (val >> 1) & 3;

 p = val & 1;

 val = rCAMDIVN;

 s = val >> 8;

 

 switch (m)

 {

  case 0:

   HCLK = FCLK;

   break;

  case 1:

   HCLK = FCLK >> 1;

   break;

  case 2:

   if(s & 2)

    HCLK = FCLK >> 3;

   else

    HCLK = FCLK >> 2;

   break;

  case 3:

   if(s & 1)

    HCLK = FCLK / 6;

   else

    HCLK = FCLK / 3;

   break;

 }

 

 if(p)

  PCLK = HCLK >> 1;

 else

  PCLK = HCLK;

 

//rUPLLCON内存的值为0x00038022,求出UPLL的值为48MHz;时钟分频控制寄存器CLKDIVN[3]=0时UCLK=UPLL

 val = rUPLLCON;

 m = (val >> 12) & 0xff;

 p = (val >> 4) & 0x3f;

 s = val & 3;

 UPLL = ((m+8)*FIN)/((p+2)*(1<<s));

 UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;

}