U-Boot移植——时钟配置

0 开发环境

    宿主机:Ubuntu14.04

    开发板:Mini2440

    U-Boot:u-boot-1.1.6 

    编译器:arm-linux-gcc

1 设置FCLKHCLKPCLK    

    根据《U-Boot移植——添加新开发板》的方法添加Mni2440的配置和目录后,打开board/mini2440/mini2440.c,在board_init()中通过修改MPLLCONUPLLCONCLKDIVN三个寄存器的值来达到设置FCLKHCLKPCLK的目的。

(1)在board_init()函数上方添加如下宏,分别表示将要设定MPLLCON、UPLLCON和CLKDIVN三个寄存器的值:

#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
#define S3C2440_UPLL_48MHZ 	((0x38<<12)|(0x02<<4)|(0x02))
#define S3C2440_CLKDIV		0x05 /* FCLK:HCLK:PCLK=1:4:8, UCLK=UPLL */

    说明:参考资料[2]P7-24指出,若要支持USB,UCLK必须为48MHz。可配置为UCLK = UPLL或者UCLK = UPLL / 2。因此UPLL只能为48MHz或者96MHz。上述配置采用了前者。

(2)添加clk_power->CLKDIVN设置,并且切换到异步总线模式:

/* FCLK:HCLK:PCLK=1:4:8 */
clk_power->CLKDIVN = S3C2440_CLKDIV;		// Added by OneSea

/* 修改为异步总线模式 */					// Added by OneSea	
__asm__( "mrc p15, 0, r1, c1, c0, 0\n"		/* Read ctrl regisger */
		 "orr r1, r1, #0xc0000000\n"			/* Asynchronous */
		 "mcr p15, 0, r1, c1, c0, 0\n"		/* Write ctrl regisger */
		 :::"r1"
		 );

    :上述设置必需添加在下面设置前面的位置。

(3)修改clk_power->MPLLCON的值

clk_power->MPLLCON = S3C2440_MPLL_400MHZ; 

(4)修改clk_power->UPLLCON的值

clk_power->UPLLCON = S3C2440_UPLL_48MHZ;

2 修改获取系统时钟的函数

    打开cpu/arm920t/s3c24x0/speed.c,分别修改get_PCLK()get_HCLKget_PLLCLK()三个函数。

(1)通过给get_PLLCLK()传递不同的函数,可以返回Mpll或者Upll的值,在S3C2440中它们的计算公式是不同的[2]P7-20,因此需要添加一个条件判断和Mpll的返回语句:

if (pllreg == UPLL)
	return((CONFIG_SYS_CLK_FREQ * m) / (p << s)); 
else
	return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); // Added

    :FCLK取Mpll,get_FCLK()函数直接返回Mpll的值:

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

(2)修改get_HCLK()

    先在get_HCLK()前面的位置定义以下宏:

#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)

    然后将get_HCLK()return语句替换为:

unsigned long clkdiv = clk_power->CLKDIVN;
unsigned long camdiv = clk_power->CAMDIVN;
int hdiv = 1;

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_HCLK3_HALF) ? 6 : 3;
	break;
}

return get_FCLK() / hdiv;

(3)修改get_PCLK(),将return语句替换为:

unsigned long clkdiv = clk_power->CLKDIVN;
unsigned long camdiv = clk_power->CAMDIVN;
int hdiv = 1;

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_HCLK3_HALF) ? 6 : 3;
	break;
}

return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);

    说明:和get_HCLK()基本一样的,只是最后的返回语句不同而已。

3 为S3C24X0_CLOCK_POWER结构添加CAMDIVN成员

    在修改get_HCLK()和get_PCLK()时候都使用clk_power->CAMDIVN,然而在u-boot-1.1.6中所定义的S3C24X0_CLOCK_POWER结构并没有CAMDIVN这个成员,因此编译上述修改后的U-Boot会出错。根据参考资料[3]的提示,我们需要为S3C24X0_CLOCK_POWER结构添加CAMDIVN成员。

    经过搜索发现上述结构定义于include/s3c24x0.h,打开该头文件,在S3C24X0_CLOCK_POWER结构的最后添加CAMDIVN成员:

typedef struct {
    S3C24X0_REG32   LOCKTIME;
    S3C24X0_REG32   MPLLCON;
    S3C24X0_REG32   UPLLCON;
    S3C24X0_REG32   CLKCON;
    S3C24X0_REG32   CLKSLOW;
    S3C24X0_REG32   CLKDIVN;
    S3C24X0_REG32   CAMDIVN;    // Added
} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER; 

4 相关设置

    由于DRAM受到系统时钟的影响,因此需要根据上述设置的系统时钟对其进行相应的修改,详见《U-Boot移植——设置SDRAM》。

参考资料

[1]韦东山. 嵌入式Linux应用开发完全手册. 人民邮电出版社,2012

[2]S3C2440A USER'S MANUAL

[3]关于uboot移植 CAMDIVN与时钟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneSea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值