cpu/arm920t/s3c2440/interrupts.c 解析

来源:互联网 发布:淘宝3d试衣技术 编辑:程序博客网 时间:2024/04/26 06:33
 

#include<commmon.h>
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_TRAB)

#if defined(CONFIG_S3C2400)
#include<s3c2400.h>
#elif defined(CONFIG_S3C2410)
#include<s3c2410.h>
#endif

#define MPLL 0
#define UPLL 1
/*
typedef struct {
    S3C24X0_REG32   LOCKTIME; //锁定时间计数寄存器
    S3C24X0_REG32   MPLLCON; //MPLL配置寄存器
    S3C24X0_REG32   UPLLCON;
    S3C24X0_REG32   CLKCON;
    S3C24X0_REG32   CLKSLOW;
    S3C24X0_REG32   CLKDIVN;
    S3C24X0_REG32   CAMDIVN;    // for s3c2440, by
www.embedsky.net
   
} S3C24X0_CLOCK_POWER;
*/
//参数pllreg的值要么为0,要么为1,通过0或1来选择是MPLL还是UPLL
static ulong get_PLLCLK(int pllreg)
{
//定义数据机构S3C24X0_CLOCK_POWER的指针clk_power指向数据结构S3C24X0_CLOCK_POWER的起始地址
          S3C24X0_CLOCK_POWER *const clk_power= S3C24X0_GetBase_CLOCK_POWER();

//通过p值来对输入频率(Fin)来进行分频的分频器P
//通过m值来对VCO的输出频率进行分频的分频器M
//通过s值来对VCO的输出频率进行分频的分频器S
//  MPLL=(2*m*Fin)/(p*(2的s次方))
// m= M (分频器M的值) + 8
// p= P (分频器P的值) + 2 
//UPLL和MPLL类似
          ulong r,m,p,s;

          if(pllreg==MPLL)(
          {
                  r=clk_power->MPLLCON;
          }
          else if(pllreg==UPLL)
          { 
                  r=clk_power->UPLLCON
          }
          else
          {        
/*
void hang (void)
{
          puts ("### ERROR ### Please RESET the board ###\n");
          for (;;);
  }
*/
                    hang();
          }
 
          m=((r&0xFF000)>>12)+8;
          p=((r&0x003F0)>>4)+2;
          s=r&0x3;
 
          if(gd->bd->bi_arch_number==MACH_TYPE_SMDK2410)
          {
                    return((CONFIG_SYS_CLK_FREQ *m)/(p<<s));
          }
          else
          {
                    return((CONFIG_SYS_CLK_FREQ *m*2)/(p<<s));
          }
}

ulong get_FCLK(void)
{
          return(get_PLLCLK(MPLL));
}


#define S3C2440_CLKDIVN_PDIVN  (1<<0)
#define S3C2440_CLKDIVN_HDIVN_MASK (3<<1)
#define S3C2440_CLKDIVN_HDIVN_1  (0<<1)
#define S3C2440_CLKDIVN_HDIVN_2  (1<<1)
#define S3C2440_CLKDIVN_HDIVN)4_8 (2<<1)
#define S3C2440_CLKDIVN_HDIVN_3_6 (3<<1)
#define S3C2440_CLKDIVN_UCLK  (1<<3)

#define S3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)
#define S3C2440_CAMDIVN_CAMCLK_SEL (1<<4)
#define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)
#define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)
#define S3C2440_CAMDIVN_DVSEN  (1<<12)

ulong get_HCLK(void)
{
          S3C24X0_CLOCK_POWER *const clk_power = S3C24X0_GetBase_CLOCK_POWER();
 
          unsigned long clkdiv;
          unsigned long camdiv;
 
          int hdiv = 1;
 
          if(gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
          {        
//时钟分频控制寄存器CLKDIVN[2:1]可知HCLK与FCLK的关系
                    return((clk_power->CLKDIVN&0x2)?get_FCLK()/2:get_FCLK());
          }
          else
          {
                    clkdiv=clk_power->CLKDIVN; //指向时钟分频控制器
                    camdiv=clk_power->CAMDIVN; //指向摄像头时钟分频控制器
  
                    switch(clkdiv & S3C2440_CLKDIVN_HDIVN_MASK)
                    {
                              case S3C2440_CLKDIVN_HDIVN_1:
   
                                        hdiv=1;
                                        break;
                              case S3C2440_CLKDIVN_HDIVN_2:
   
                                        hdiv=2;
                                        break;
                              case SeC2440_CLKDIVN_HDIVN_4_8:
   
                                        hdiv=(camdiv & S3c2440_CAMDIVN_HCLK4_HALF)?8:4;
                                        break;
                              case S3C2440_CLKDIVN_HDIVN_3_6:
   
                                        hdiv=(camdiv * S3C2440_CAMDIVN_HCLK3_HALF)?6:3;
                                        break;
                    }
  
                    return get_FCLK()/hdiv;
          }
 
}

ulong get_PCLK(void)
{
          S3C24X0_CLOCK_POWER *const clk_power=S3C24X0_GetBase_CLOCK_POWER();
 
          unsigned long clkdiv;
          unsigned long camdiv;
 
          int hdiv=1;
 
          if(gd->bd->bi_arch_number==MACH_TYPE_SMDK2410)
          {
                    return((clk_power->CLKDIVN & 0x1)?get_HCLK()/2:get_HCLK());
          }
          else
          {
                    clkdiv=clk_power->CLKDIVN;
                    camdiv=clk_power->CAMDIVN;
  
                    switch(clkdiv & S3C2440_CLKDIVN_HDIVN_MASK)
                    {
                              case S3C2440_CLKDIVN_HDIVN_1:
   
                                        hdiv=1;
                                        break; 
                              case S3C2440_CLKDIVN_HDIVN_2:
   
                                        hdiv=2;
                                        break; 
                              case S3C2440_CLKDIVN_HDIVN_4_8:
    
                                        hdiv=(camdiv & S3C2440_CAMDIVN_HCLK4_HALF)?8:4;
                                        break;
                              case S3C2440_CLKDIVN_HDIVN_3_6:
    
                                        hdiv=(camdiv & S3C2440_CAMDIVN_HCLK4_HALF)?6:3;
                                        break;
                     }
  
                    return get_FCLK()/hdiv/((clkdiv&S3C2440_CLKDIVN_PDIVN)?2:1);
          }
 
}

ulong get_UCLK(void)
{
          return(get_PLLCLK(UPLL));
}

#endif
/*
注:MPLL提供最终的CPU核使用度时钟FCLK
 UPLL提供最终的USB使用的时钟UCLK=48MHz
锁定时间计数寄存器LOCKTIME的作用就是:CPU刚上电,MPLL不会立即工作(不稳定),所以要等待MPLL稳定后才能使用作为CPU时钟
 FCLK:CPU内核使用的时钟
 HCLK:CPU高速外设使用的时钟
 FCLK:CPU低速外设使用的时钟
 UCLK:USB,CAMERA使用的时钟
 
设定FCLK核UCLK完全是由MPLLCON和UPLLCON来决定的,具体牵扯到MDIV,PDIV,SDIV,计算公式如下:
       FCLK/UCLK=(2*m*Fin)/(p*(2的s次方))
HCLK,PCLK与FLCK的关系是由时钟分频控制寄存器CLKDIVN[2:1],[0]的相应值和CAMDIVN[9],[8]联合作用的
UCLK,的值是由CLKDIVN[3]的值来决定的
*/