U-Boot主要目录结构
- board 目标板相关文件,主要包含SDRAM、FLASH驱动;
- common 独立于处理器体系结构的通用代码,如内存大小探测与故障检测;
- cpu 与处理器相关的文件。如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件;
- driver 通用设备驱动,如CFI FLASH驱动(目前对INTEL FLASH支持较好)
- doc U-Boot的说明文档;
- examples可在U-Boot下运行的示例程序;如hello_world.c,timer.c;
- include U-Boot头文件;尤其configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件;
- lib_xxx 处理器体系相关的文件,如lib_ppc, lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件;
- net 与网络功能相关的文件目录,如bootp,nfs,tftp;
- post 上电自检文件目录。尚有待于进一步完善;
- rtc RTC驱动程序;
- tools 用于创建U-Boot S-RECORD和BIN镜像文件的工具;
一、建立自己的开发板文件
1.在borad文件夹中新建自己的板子目录,复制sbc2410x中的文件到此目录,作为蓝本,加快移植进度,修改板子目录下的makefile文件COBJS := tq2440.o flash.o(其中tq2440.o文件的生成必须要修改此目录下的sbc2410x.c文件)
2.在include/configs文件夹下以sbc2410x.h为蓝本,创建tq2440.h文件
3.修改uboot根目录下的makefile文件,确定CROSS_COMPLE即编译器选项,加入make选项:
tq2440_config:unconfig
(TAB)@./mkconfig $(@:_config=) arm arm920t tq2440 NULL s3c24x0
其中:
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。
tq2440: 开发板的型号(BOARD),对应于board/tq2440目录。
NULL: 开发者/或经销商(vender)。
s3c24x0: 片上系统(SOC)。
4.接下来测试是否能编译通过,执行:make disclean--删除原来的编译结果
make tqconfig
成功后出现Configuring for xxx board.....
make –可以生成uboot.bin文件
二、修改源码
1、修改start.S
修改如下代码:
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
#ifdefined(CONFIG_S3C2440)
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
#if0
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif
#endif
#ifndefCONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
//把堆栈初始化拿到前面来,应为后面要写的时钟初始化函数会用到堆栈
stack_setup:
ldr r0, _TEXT_BASE
sub r0, r0, #CFG_MALLOC_LEN
sub r0, r0, #CFG_GBL_DATA_SIZE
#ifdefCONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12
//跳转到时钟初始话函数
bl clock_init
#ifndefCONFIG_SKIP_RELOCATE_UBOOT
relocate:
adr r0, _start
ldr r1, _TEXT_BASE
cmp r0, r1
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2
//屏蔽原先代码,重写代码搬运函数
#if1
bl CopyCode2Ram
#else
add r2, r0, r2
copy_loop:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble copy_loop
#endif
#endif
接着在include/configs/tq2440.h添加
#define CONFIG_S3C2440 1
#define CONFIG_TQ2440 1
并屏蔽原先的芯片和开发板定义,与此同时s3c24x0.h中的S3C24X0_GPIO结构体也要改写,使其支持2440,而且要添加
S3C24X0_REG32 res9[4];
S3C24X0_REG32 GPJCON;
S3C24X0_REG32 GPJDAT;
S3C24X0_REG32 GPJUP;
此为GPIO_J口的定义
添加typedefstruct{
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCONT;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFMECCD0;
S3C24X0_REG32 NFMECCD1;
S3C24X0_REG32 NFSECCD;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFESTAT0;
S3C24X0_REG32 NFESTAT1;
S3C24X0_REG32 NFMECC0;
S3C24X0_REG32 NFMECC1;
S3C24X0_REG32 NFSECC;
S3C24X0_REG32 NFSBLK;
S3C24X0_REG32 NFEBLK;
} S3C2440_NAND;
其他结构体也要修改
修改lowlevel_init.S,修改54,58,126行即可,即外部存储器控制器。
54 #defineB1_BWSCON (DW16)
58 #defineB5_BWSCON (DW8)
126 #defineREFCNT 0x4f4
lowlevel_init.S 主要设置SDRAM配置
ARM的存储器控制器
位宽和等待控制寄存器BWSCON中每4位控制一个BANK,最高4位对应BANK7、接下来4位对应BANK6,依此类推
8 个存储器 banks
6 个是 ROM,SRAM 等类型存储器 bank
2 个是可以作为 ROM、SRAM、SDRAM 等存储器 bank
BANK控制寄存器BANKCONx(BANKCON1~5)这几个寄存器用来控制BANK0~BANK5外接设备的访问时序,一般使用默认的0x0700即可。
BANK控制寄存器BANKCONx(BANKCON6~7,在8个BANK中,只有BANK6和BANK7可以外接SRAM和SDRAM,所以BANKCON6~BANKCON7与BANKCON0~BANKCON5有点不同。
在board文件夹中添加boot_init.c文件,并修改makefile(boot_init.c文件主要包含nand的读写,时钟的初始化,和代码的拷贝函数)
boot_init.c
#include<common.h>
#include<s3c2410.h>
#defineGSTATUS1 (*(volatileunsignedint*)0x560000B0)
#defineBUSY 1
#defineNAND_SECTOR_SIZE 512
#defineNAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
#defineNAND_SECTOR_SIZE_LP 2048
#defineNAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1)
charbLARGEBLOCK; //HJ_add 20090807
charb128MB; //HJ_add 20090807
voidnand_init_ll(void);
intnand_read_ll(unsignedchar*buf, unsignedlongstart_addr, intsize);
intnand_read_ll_lp(unsignedchar*buf, unsignedlongstart_addr, intsize);
staticvoidnand_reset(void);
staticvoidwait_idle(void);
staticvoidnand_select_chip(void);
staticvoidnand_deselect_chip(void);
staticvoidwrite_cmd(intcmd);
staticvoidwrite_addr(unsignedintaddr);
staticvoidwrite_addr_lp(unsignedintaddr);
staticunsignedcharread_data(void);
intNF_ReadID(void); //HJ_add 20090807
staticvoids3c2440_nand_reset(void);
staticvoids3c2440_wait_idle(void);
staticvoids3c2440_nand_select_chip(void);
staticvoids3c2440_nand_deselect_chip(void);
staticvoids3c2440_write_cmd(intcmd);
staticvoids3c2440_write_addr(unsignedintaddr);
staticvoids3c2440_write_addr_lp(unsignedintaddr);
staticunsignedchars3c2440_read_data(void);
staticvoids3c2440_nand_reset(void)
{
s3c2440_nand_select_chip();
s3c2440_write_cmd(0xff); // 复位命令
s3c2440_wait_idle();
s3c2440_nand_deselect_chip();
}
staticvoids3c2440_wait_idle(void)
{
inti;
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
volatileunsignedchar*p = (volatileunsignedchar*)&s3c2440nand->NFSTAT;
while(!(*p & BUSY))
for(i=0; i<10; i++);
}
staticvoids3c2440_nand_select_chip(void)
{
inti;
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
s3c2440nand->NFCONT&= ~(1<<1);
for(i=0; i<10; i++);
}
staticvoids3c2440_nand_deselect_chip(void)
{
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
s3c2440nand->NFCONT|= (1<<1);
}
staticvoids3c2440_write_cmd(intcmd)
{
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
volatileunsignedchar*p = (volatileunsignedchar*)&s3c2440nand->NFCMD;
*p = cmd;
}
staticvoids3c2440_write_addr(unsignedintaddr)
{
inti;
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
volatileunsignedchar*p = (volatileunsignedchar*)&s3c2440nand->NFADDR;
*p = addr & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 9) & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 17) & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 25) & 0xff;
for(i=0; i<10; i++);
}
staticvoids3c2440_write_addr_lp(unsignedintaddr)
{
inti;
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
volatileunsignedchar*p = (volatileunsignedchar*)&s3c2440nand->NFADDR;
intcol, page;
col = addr & NAND_BLOCK_MASK_LP;
page = addr / NAND_SECTOR_SIZE_LP;
*p = col & 0xff;
for(i=0; i<10; i++);
*p = (col >> 8) & 0x0f;
for(i=0; i<10; i++);
*p = page & 0xff;
for(i=0; i<10; i++);
*p = (page >> 8) & 0xff;
for(i=0; i<10; i++);
if(b128MB == 0)
*p = (page >> 16) & 0x03;
for(i=0; i<10; i++);
}
staticunsignedchars3c2440_read_data(void)
{
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
volatileunsignedchar*p = (volatileunsignedchar*)&s3c2440nand->NFDATA;
return*p;
}
staticvoidnand_reset(void)
{
s3c2440_nand_reset();
}
staticvoidwait_idle(void)
{
s3c2440_wait_idle();
}
staticvoidnand_select_chip(void)
{
inti;
s3c2440_nand_select_chip();
for(i=0; i<10; i++);
}
staticvoidnand_deselect_chip(void)
{
s3c2440_nand_deselect_chip();
}
staticvoidwrite_cmd(intcmd)
{
s3c2440_write_cmd(cmd);
}
staticvoidwrite_addr(unsignedintaddr)
{
s3c2440_write_addr(addr);
}
staticvoidwrite_addr_lp(unsignedintaddr)
{
s3c2440_write_addr_lp(addr);
}
staticunsignedcharread_data(void)
{
returns3c2440_read_data();
}
voidnand_init_ll(void)
{
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
#defineTACLS 0
#defineTWRPH0 3
#defineTWRPH1 0
//设置时序
s3c2440nand->NFCONF= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
// 使能NAND Flash控制器, 初始化ECC, 禁止片选
s3c2440nand->NFCONT= (1<<4)|(1<<1)|(1<<0);
// 复位NAND Flash
nand_reset();
}
#if1
intNF_ReadID(void)
{
charpMID;
charpDID;
int nBuff;
char n4thcycle;
inti;
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
volatileunsignedchar*p = (volatileunsignedchar*)&s3c2440nand->NFADDR;
b128MB = 1;
n4thcycle = nBuff = 0;
nand_init_ll();
nand_select_chip();
write_cmd(0x90); // read id command
*p=0x00 & 0xff;
for( i = 0; i < 100; i++ );
pMID = read_data();
pDID = read_data();
nBuff = read_data();
n4thcycle = read_data();
nand_deselect_chip();
if(pDID >= 0xA0)
{
b128MB = 0;
}
return(pDID);
}
#endif
intnand_read_ll(unsignedchar*buf, unsignedlongstart_addr, intsize)
{
inti, j;
chardat;
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
volatileunsignedchar*p = (volatileunsignedchar*)&s3c2440nand->NFADDR;
if((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
{
return-1;
}
nand_select_chip();
for(i=start_addr; i < (start_addr + size);)
{
if(1){
write_cmd(0x50);
*p = 5;
for(j=0; j<10; j++);
*p = (i >> 9) & 0xff;
for(j=0; j<10; j++);
*p = (i >> 17) & 0xff;
for(j=0; j<10; j++);
*p = (i >> 25) & 0xff;
for(j=0; j<10; j++);
wait_idle();
dat = read_data();
write_cmd(0);
nand_deselect_chip();
if(dat != 0xff)
{
i += 16384; // 1 Block = 512*32= 16384
printf("Bad block at 0x%lx,will be skipped1n",i);
}
nand_select_chip();
}
write_cmd(0);
write_addr(i);
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE; j++, i++)
{
*buf = read_data();
buf++;
}
}
nand_deselect_chip();
return0;
}
intnand_read_ll_lp(unsignedchar*buf, unsignedlongstart_addr, intsize)
{
inti, j;
chardat;
S3C2440_NAND* s3c2440nand = (S3C2440_NAND*)0x4e000000;
volatileunsignedchar*p = (volatileunsignedchar*)&s3c2440nand->NFADDR;
if((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP))
{
return-1;
}
nand_select_chip();
for(i=start_addr; i < (start_addr + size);)
{
if(1){
intcol, page;
col = i & NAND_BLOCK_MASK_LP;
page = i / NAND_SECTOR_SIZE_LP;
write_cmd(0x00);
*p = 5;
for(j=0; j<10; j++);
*p = 8;
for(j=0; j<10; j++);
*p = page & 0xff;
for(j=0; j<10; j++);
*p = (page >> 8) & 0xff;
for(j=0; j<10; j++);
if(b128MB == 0)
*p = (page >> 16) & 0x03;
for(j=0; j<10; j++);
write_cmd(0x30);
wait_idle();
dat = read_data();
nand_deselect_chip();
if(dat != 0xff)
{
i += 131072; // 1 Block = 2048*64= 131072
}
nand_select_chip();
}
write_cmd(0);
write_addr_lp(i);
write_cmd(0x30);
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++)
{
*buf = read_data();
buf++;
}
}
nand_deselect_chip();
return0;
}
intbBootFrmNORFlash(void)
{
volatileunsignedint*pdw = (volatileunsignedint*)0;
unsignedintdwVal;
dwVal = *pdw;
*pdw = 0x12345678;
if(*pdw != 0x12345678)
{
return1;
}
else
{
*pdw = dwVal;
return0;
}
}
intCopyCode2Ram(unsignedlongstart_addr, unsignedchar*buf, intsize)
{
unsignedint*pdwDest;
unsignedint*pdwSrc;
inti;
long*GPBCON=0x56000010;
long*GPBDAT=0x56000014;
long*GPBUP =0x56000018;
*GPBCON=0x295551;
*GPBUP=0xff;
*GPBDAT=0x7be;
if(bBootFrmNORFlash())
{
pdwDest = (unsignedint*)buf;
pdwSrc = (unsignedint*)start_addr;
for(i = 0; i < size / 4; i++)
{
pdwDest[i] = pdwSrc[i];
}
return0;
}
else
{
nand_init_ll();
if(NF_ReadID() == 0x76 )
{
nand_read_ll(buf, start_addr, (size + NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK));}
else
{
nand_read_ll_lp(buf, start_addr, (size + NAND_BLOCK_MASK_LP)&~(NAND_BLOCK_MASK_LP));}
return0;
}
}
staticinlinevoiddelay(unsignedlongloops)
{
__asm__volatile("1:n"
"subs %0, %1, #1n"
"bne1b":"=r"(loops):"0"(loops));
}
#defineS3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01)) //HJ 400MHz
#defineS3C2440_MPLL_405MHZ ((0x7f<<12)|(0x02<<4)|(0x01)) //HJ 405MHz
#defineS3C2440_MPLL_440MHZ ((0x66<<12)|(0x01<<4)|(0x01)) //HJ 440MHz
#defineS3C2440_MPLL_480MHZ ((0x98<<12)|(0x02<<4)|(0x01)) //HJ 480MHz
#defineS3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
#defineS3C2440_MPLL_100MHZ ((0x5c<<12)|(0x01<<4)|(0x03))
#defineS3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02)) //HJ 100MHz
#defineS3C2440_CLKDIV 0x05 //HJ 100MHz
#defineS3C2440_CLKDIV136 0x07 //HJ 133MHz
#defineS3C2440_CLKDIV188 0x04
#defineS3C2440_CAMDIVN188 ((0<<8)|(1<<9))
#defineS3C2440_MPLL_399MHz ((0x6e<<12)|(0x03<<4)|(0x01))
#defineS3C2440_UPLL_48MHZ_Fin16MHz ((60<<12)|(4<<4)|(2))
voidclock_init(void)
{
S3C24X0_CLOCK_POWER*clk_power = (S3C24X0_CLOCK_POWER*)0x4C000000;
#ifCONFIG_133MHZ_SDRAM
clk_power->CLKDIVN = S3C2440_CLKDIV136; //HJ 1:3:6
#else
clk_power->CLKDIVN= S3C2440_CLKDIV; //HJ 1:4:8
#endif
__asm__( "mrc p15, 0, r1, c1, c0, 0n"
"orr r1, r1, #0xc0000000n"
"mcr p15, 0, r1, c1, c0, 0n"
:::"r1"
);
clk_power->LOCKTIME= 0xFFFFFF;
clk_power->UPLLCON= S3C2440_UPLL_48MHZ; //fin=12.000MHz
// clk_power->UPLLCON = S3C2440_UPLL_48MHZ_Fin16MHz; //fin=16.934MHz
delay (4000);
clk_power->MPLLCON= S3C2440_MPLL_400MHZ; //fin=12.000MHz
// clk_power->MPLLCON = S3C2440_MPLL_405MHZ; //HJ 405MHz
// clk_power->MPLLCON = S3C2440_MPLL_440MHZ; //HJ 440MHz
// clk_power->MPLLCON = S3C2440_MPLL_480MHZ; //HJ 480MHz
// clk_power->MPLLCON = S3C2440_MPLL_399MHz; //fin=16.934MHz
delay (8000);
}
修改cpu/arm920t/s3c24x0/speed.c中get_HCLK等函数,首先在前面添加DECLARE_GLOBAL_DATA_PTR;使其能使用gd_t全局数据结构的指针
FLCK、HCLK和PCLK的关系
S3C2440有三个时钟FLCK、HCLK和PCLK
FCLK is used by ARM920T,内核时钟,主频。
HCLK is used for AHB bus, which is used by the ARM920T, the memory controller, the interrupt controller, the LCD controller, the DMA and USB host block. 也就是总线时钟,包括USB时钟。
PCLK is used for APB bus, which is used by the peripherals such as WDT, IIS, I2C, PWM timer, MMC interface,ADC, UART, GPIO, RTC and SPI.即IO接口时钟,例如串口的时钟设置就是从PCLK来的;
具体代码:
staticulongget_PLLCLK(intpllreg)
{
S3C24X0_CLOCK_POWER* constclk_power = S3C24X0_GetBase_CLOCK_POWER();
ulongr, m, p, s;
if(pllreg == MPLL)
r = clk_power->MPLLCON;
elseif(pllreg == UPLL)
r = clk_power->UPLLCON;
else
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));
}
ulongget_FCLK(void)
{
return(get_PLLCLK(MPLL));
}
#defineS3C2440_CLKDIVN_PDIVN (1<<0)
#defineS3C2440_CLKDIVN_HDIVN_MASK (3<<1)
#defineS3C2440_CLKDIVN_HDIVN_1 (0<<1)
#defineS3C2440_CLKDIVN_HDIVN_2 (1<<1)
#defineS3C2440_CLKDIVN_HDIVN_4_8 (2<<1)
#defineS3C2440_CLKDIVN_HDIVN_3_6 (3<<1)
#defineS3C2440_CLKDIVN_UCLK (1<<3)
#defineS3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)
#defineS3C2440_CAMDIVN_CAMCLK_SEL (1<<4)
#defineS3C2440_CAMDIVN_HCLK3_HALF (1<<8)
#defineS3C2440_CAMDIVN_HCLK4_HALF (1<<9)
#defineS3C2440_CAMDIVN_DVSEN (1<<12)
ulongget_HCLK(void)
{
S3C24X0_CLOCK_POWER* constclk_power = S3C24X0_GetBase_CLOCK_POWER();
unsignedlongclkdiv;
unsignedlongcamdiv;
inthdiv = 1;
clkdiv = clk_power->CLKDIVN;
camdiv = clk_power->CAMDIVN;
if(gd->bd->bi_arch_number== MACH_TYPE_SMDK2410)
return((clk_power->CLKDIVN& 0x2) ? get_FCLK()/2 : get_FCLK());
else
{
switch(clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
caseS3C2440_CLKDIVN_HDIVN_1:
hdiv = 1;
break;
caseS3C2440_CLKDIVN_HDIVN_2:
hdiv = 2;
break;
caseS3C2440_CLKDIVN_HDIVN_4_8:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
break;
caseS3C2440_CLKDIVN_HDIVN_3_6:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
break;
}
returnget_FCLK() / hdiv;
}
}
ulongget_PCLK(void)
{
S3C24X0_CLOCK_POWER* constclk_power = S3C24X0_GetBase_CLOCK_POWER();
unsignedlongclkdiv;
unsignedlongcamdiv;
inthdiv = 1;
clkdiv = clk_power->CLKDIVN;
camdiv = clk_power->CAMDIVN;
if(gd->bd->bi_arch_number== MACH_TYPE_SMDK2410)
return((clk_power->CLKDIVN& 0x1) ? get_HCLK()/2 : get_HCLK());
else
{
switch(clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
caseS3C2440_CLKDIVN_HDIVN_1:
hdiv = 1;
break;
caseS3C2440_CLKDIVN_HDIVN_2:
hdiv = 2;
break;
caseS3C2440_CLKDIVN_HDIVN_4_8:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
break;
caseS3C2440_CLKDIVN_HDIVN_3_6:
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
break;
}
returnget_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
}
}