一. 代码修改
UBOOT从arch\arm\cpu\arm920t\start.s开始运行。
start.s主要负责设置CPU模式,初始化时钟、中断、看门狗、SDRAM,初始化堆栈等工作,并拷贝自己到内存中,然后从加载地址跳转到内存中的运行地址处,之后的就是C程序了。
首先修改时钟初始化代码,将start.s中原来的2410时钟初始化代码删除,增加一句 [bl clock_init]实现时钟初始化。
函数clock_init在文件boot_init.c中,此文件可以从TQ2440的UBOOT中拷贝过来放到board\samsung\TQ2440下,它包含了时钟初始化函数(clock_init)以及从NAND拷贝UBOOT到SDRAM的函数(CopyCode2Ram)。注意,需要修改board\samsung\TQ2440下的MAKEFILE文件:COBJS := TQ2440.o flash.o boot_init.o。
从TQ2440的UBOOT拷贝过来的boot_init.c需要修改一下头文件(修改后的boot_init.c见最后),并在arch\arm\include\asm\arch-s3c24x0\s3c24x0.h中增加
1 /* NAND FLASH (see S3C2410 manual chapter 6) */ 2 typedef struct { 3 u32 NFCONF; 4 u32 NFCMD; 5 u32 NFADDR; 6 u32 NFDATA; 7 u32 NFSTAT; 8 u32 NFECC; 9 } /*__attribute__((__packed__))*/ S3C2410_NAND; 10 11 /* NAND FLASH (see S3C2440 manual chapter 6, www.embedsky.net) */ 12 typedef struct { 13 u32 NFCONF; 14 u32 NFCONT; 15 u32 NFCMD; 16 u32 NFADDR; 17 u32 NFDATA; 18 u32 NFMECCD0; 19 u32 NFMECCD1; 20 u32 NFSECCD; 21 u32 NFSTAT; 22 u32 NFESTAT0; 23 u32 NFESTAT1; 24 u32 NFMECC0; 25 u32 NFMECC1; 26 u32 NFSECC; 27 u32 NFSBLK; 28 u32 NFEBLK; 29 } /*__attribute__((__packed__))*/ S3C2440_NAND;
删除board\samsung\TQ2440\TQ2440.c里board_init函数的时钟配置部分(也包括此文件里的时钟相关宏)。并修改下面的机器码为:
/* arch number of SMDK2410-Board */ if(gpio->GSTATUS1==0x32440001)S3C2440 gd->bd->bi_arch_number = MACH_TYPE_TQ2440; else gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
由于后面的C程序在初始化串口时需要获得主时钟,因此需要修改arch/arm/cpu/arm920t/s3c24x0目录下的speed.c里面的get_PLLCLK和get_HCLK函数。
因为2410和2440的看门狗寄存器一样,不作修改。而中断控制寄存器不同,需要修改代码。
start.s里调用cpu_init_crit函数,而cpu_init_crit又去调用lowlevel_init.S的代码,这部分主要实现SDRAM的初始化,需要根据SDRAM的参数修改lowlevel_init.S文件(可以直接拷贝开发板自带UBOOT里的lowlevel_init.S)。
start.s下 标号“relocate:”的部分实现了UBOOT的重定位,首先通过ADR指令得到当前代码的入口处地址_start(相对PC根据偏移值计算得到),然后得到UBOOT需要被搬移到内存中的地址_TEXT_BASE,在计算出需要搬移部分(uboot的代码)的大小后,执行拷贝工作“copy_loop:”。
copy_loop只能实现从NOR FLASH或者SDRAM拷贝到SDRAM,而从NAND启动时需要其他函数来实现代码拷贝,这个函数在boot_init.c中被实现,因此从NAND启动时用"bl CopyCode2Ram"替代"copy_loop"即可。注意,boot_init.c中NAND部分的代码与UBOOT自己的NAND驱动部分无关,只完成代码拷贝。
二.下载程序到开发板
1) 为了把我们的UBOOT代码用开发板自带的UBOOT加载到SDRAM里运行,需要注释掉start.s里的cpu_init_crit,因为在这种情况下,当前运行的代码是在SDRAM中跑的,不能再次进行配置。用"copy_loop"实现复制,并注释掉"bl CopyCode2Ram"。
最后,修改board/samsung/TQ2440/config.mk里的TEXT_BASE = 0x33A80000。编译并用dnw加载到SDRAM的0x30000000处运行即可(程序会重定位到TEXT_BASE指定的位置运行)。
2) 如果希望NAND启动,则注释掉"copy_loop"部分,打开"bl CopyCode2Ram",打开“cpu_init_crit”。把开发板切换成NOR FLASH启动模式并上电,在开发板自带UBOOT的菜单中选择(1),通过dnw下载u-boot.bin到NAND中。开发板断点,切换到NAND启动模式上电即可。
注意:至此还存在一个陷阱,2440在NAND启动模式下将NAND的前4K拷贝到SOC内部的RAM中运行(映射到0x00000000地址),因此必须在这4K代码空间中包含往C程序跳转(start.s中的"ldr pc, _start_armboot")之前的代码。所以需要修改一下根目录下的u-boot.lds文件以调整boot_init.o和lowlevel_init.o的位置到前4K中:
1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2 OUTPUT_ARCH(arm) 3 ENTRY(_start) 4 SECTIONS 5 { 6 . = 0x00000000; 7 . = ALIGN(4); 8 .text : 9 { 10 arch/arm/cpu/arm920t/start.o (.text) 11 board/samsung/TQ2440/lowlevel_init.o (.text) 12 board/samsung/TQ2440/boot_init.o (.text) 13 *(.text) 14 } 15 . = ALIGN(4); 16 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } 17 . = ALIGN(4); 18 .data : { *(.data) } 19 . = ALIGN(4); 20 .got : { *(.got) } 21 . = .; 22 __u_boot_cmd_start = .; 23 .u_boot_cmd : { *(.u_boot_cmd) } 24 __u_boot_cmd_end = .; 25 . = ALIGN(4); 26 __bss_start = .; 27 .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } 28 _end = .; 29 }
三.部分代码参考
在UBOOT跳转到C部分并初始化串口之前,主要的调试手段是点亮开发板上的4个LED,在start.s里LED的IO配置及操作如下:
1 #define GPBCON 0x56000010 2 #define GPBDAT 0x56000014 3 #define GPBUP 0x56000018 4 5 ldr r2, =0x7ff 6 ldr r1, =GPBUP 7 str r2, [r1] 8 9 ldr r2, =0x15400 10 ldr r1, =GPBCON 11 str r2, [r1] 12 13 ldr r2, =0x1F0 14 ldr r1, =GPBDAT 15 str r2, [r1]
修改后的start.s:
1 /* 2 * armboot - Startup Code for ARM920 CPU-core 3 * 4 * Copyright (c) 2001 Marius Gr鰃er <mag@sysgo.de> 5 * Copyright (c) 2002 Alex Z黳ke <azu@sysgo.de> 6 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 */ 26 27 #include <common.h> 28 #include <config.h> 29 30 #define EXCUTE_IN_NAND 1 31 32 /* 33 ************************************************************************* 34 * 35 * Jump vector table as in table 3.1 in [1] 36 * 37 ************************************************************************* 38 */ 39 40 41 .globl _start 42 _start: b start_code 43 ldr pc, _undefined_instruction 44 ldr pc, _software_interrupt 45 ldr pc, _prefetch_abort 46 ldr pc, _data_abort 47 ldr pc, _not_used 48 ldr pc, _irq 49 ldr pc, _fiq 50 51 _undefined_instruction: .word undefined_instruction 52 _software_interrupt: .word software_interrupt 53 _prefetch_abort: .word prefetch_abort 54 _data_abort: .word data_abort 55 _not_used: .word not_used 56 _irq: .word irq 57 _fiq: .word fiq 58 59 .balignl 16,0xdeadbeef 60 61 62 /* 63 ************************************************************************* 64 * 65 * Startup Code (called from the ARM reset exception vector) 66 * 67 * do important init only if we don‘t start from memory! 68 * relocate armboot to ram 69 * setup stack 70 * jump to second stage 71 * 72 ************************************************************************* 73 */ 74 75 _TEXT_BASE: 76 .word TEXT_BASE 77 78 .globl _armboot_start 79 _armboot_start: 80 .word _start 81 82 /* 83 * These are defined in the board-specific linker script. 84 */ 85 .globl _bss_start 86 _bss_start: 87 .word __bss_start 88 89 .globl _bss_end 90 _bss_end: 91 .word _end 92 93 #if defined (CONFIG_USE_IRQ) 94 /* IRQ stack memory (calculated at run-time) */ 95 .globl IRQ_STACK_START 96 IRQ_STACK_START: 97 .word 0x0badc0de 98 99 /* IRQ stack memory (calculated at run-time) */ 100 .globl FIQ_STACK_START 101 FIQ_STACK_START: 102 .word 0x0badc0de 103 #endif 104 105 106 /* 107 * the actual start code 108 */ 109 110 start_code: 111 /* 112 * set the cpu to SVC32 mode 113 */ 114 mrs r0, cpsr 115 bic r0, r0, #0x1f 116 orr r0, r0, #0xd3 117 msr cpsr, r0 118 119 /* turn off the watchdog */ 120 121 # if defined (CONFIG_S3C2400) 122 # define pWTCON 0x15300000 123 # define INTMSK 0x14400008 /* Interupt-Controller base addresses */ 124 # define CLKDIVN 0x14800014 /* clock divisor register */ 125 #elif defined(CONFIG_S3C2410) 126 # define pWTCON 0x53000000 127 # define INTMOD 0X4A000004 128 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ 129 # define INTSUBMSK 0x4A00001C 130 # define CLKDIVN 0x4C000014 /* clock divisor register */ 131 #endif 132 ldr r0, =pWTCON 133 mov r1, #0x0 134 str r1, [r0] 135 136 /* 137 * mask all IRQs by setting all bits in the INTMR - default 138 */ 139 mov r1, #0xffffffff 140 ldr r0, =INTMSK 141 str r1, [r0] 142 143 ldr r1, =0x7fff 144 ldr r0, =INTSUBMSK 145 str r1, [r0] 146 147 148 /* 149 * we do sys-critical inits only at reboot, 150 * not when booting from ram! 151 */ 152 153 #if EXCUTE_IN_NAND 154 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 155 bl cpu_init_crit 156 #endif 157 #endif 158 159 stack_setup: 160 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 161 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 162 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 163 #if defined (CONFIG_USE_IRQ) 164 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 165 #endif 166 sub sp, r0, #12 /* leave 3 words for abort-stack */ 167 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 168 169 /* LED Init*/ 170 #define GPBCON 0x56000010 171 #define GPBDAT 0x56000014 172 #define GPBUP 0x56000018 173 174 ldr r2, =0x7ff 175 ldr r1, =GPBUP 176 str r2, [r1] 177 178 ldr r2, =0x15400 179 ldr r1, =GPBCON 180 str r2, [r1] 181 182 ldr r2, =0x1F0 183 ldr r1, =GPBDAT 184 str r2, [r1] 185 186 bl clock_init 187 188 #ifndef CONFIG_SKIP_RELOCATE_UBOOT 189 relocate: /* relocate U-Boot to RAM */ 190 adr r0, _start /* r0 <- current position of code */ 191 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 192 cmp r0, r1 /* don‘t reloc during debug */ 193 beq clear_bss 194 195 ldr r2, _armboot_start 196 ldr r3, _bss_start 197 sub r2, r3, r2 /* r2 <- size of armboot */ 198 #if EXCUTE_IN_NAND /* BOOT FROM NAND */ 199 bl CopyCode2Ram /* r0: source, r1: dest, r2: size */ 200 #else 201 /* BOOt FROM NOR */ 202 add r2, r0, r2 /* r2 <- source end address */ 203 204 copy_loop: 205 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 206 stmia r1!, {r3-r10} /* copy to target address [r1] */ 207 cmp r0, r2 /* until source end addreee [r2] */ 208 ble copy_loop 209 #endif 210 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 211 212 clear_bss: 213 ldr r0, _bss_start /* find start of bss segment */ 214 ldr r1, _bss_end /* stop here */ 215 mov r2, #0x00000000 /* clear */ 216 217 clbss_l:str r2, [r0] /* clear loop... */ 218 add r0, r0, #4 219 cmp r0, r1 220 ble clbss_l 221 222 ldr pc, _start_armboot 223 224 _start_armboot: .word start_armboot 225 226 227 /* 228 ************************************************************************* 229 * 230 * CPU_init_critical registers 231 * 232 * setup important registers 233 * setup memory timing 234 * 235 ************************************************************************* 236 */ 237 238 239 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 240 cpu_init_crit: 241 /* 242 * flush v4 I/D caches 243 */ 244 mov r0, #0 245 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 246 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 247 248 /* 249 * disable MMU stuff and caches 250 */ 251 mrc p15, 0, r0, c1, c0, 0 252 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 253 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 254 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 255 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 256 mcr p15, 0, r0, c1, c0, 0 257 258 /* 259 * before relocating, we have to setup RAM timing 260 * because memory timing is board-dependend, you will 261 * find a lowlevel_init.S in your board directory. 262 */ 263 mov ip, lr 264 265 bl lowlevel_init 266 267 mov lr, ip 268 mov pc, lr 269 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 270 271 /* 272 ************************************************************************* 273 * 274 * Interrupt handling 275 * 276 ************************************************************************* 277 */ 278 279 @ 280 @ IRQ stack frame. 281 @ 282 #define S_FRAME_SIZE 72 283 284 #define S_OLD_R0 68 285 #define S_PSR 64 286 #define S_PC 60 287 #define S_LR 56 288 #define S_SP 52 289 290 #define S_IP 48 291 #define S_FP 44 292 #define S_R10 40 293 #define S_R9 36 294 #define S_R8 32 295 #define S_R7 28 296 #define S_R6 24 297 #define S_R5 20 298 #define S_R4 16 299 #define S_R3 12 300 #define S_R2 8 301 #define S_R1 4 302 #define S_R0 0 303 304 #define MODE_SVC 0x13 305 #define I_BIT 0x80 306 307 /* 308 * use bad_save_user_regs for abort/prefetch/undef/swi ... 309 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 310 */ 311 312 .macro bad_save_user_regs 313 sub sp, sp, #S_FRAME_SIZE 314 stmia sp, {r0 - r12} @ Calling r0-r12 315 ldr r2, _armboot_start 316 sub r2, r2, #(CONFIG_STACKSIZE) 317 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) 318 /* set base 2 words into abort stack */ 319 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) 320 ldmia r2, {r2 - r3} @ get pc, cpsr 321 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 322 323 add r5, sp, #S_SP 324 mov r1, lr 325 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 326 mov r0, sp 327 .endm 328 329 .macro irq_save_user_regs 330 sub sp, sp, #S_FRAME_SIZE 331 stmia sp, {r0 - r12} @ Calling r0-r12 332 add r7, sp, #S_PC 333 stmdb r7, {sp, lr}^ @ Calling SP, LR 334 str lr, [r7, #0] @ Save calling PC 335 mrs r6, spsr 336 str r6, [r7, #4] @ Save CPSR 337 str r0, [r7, #8] @ Save OLD_R0 338 mov r0, sp 339 .endm 340 341 .macro irq_restore_user_regs 342 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 343 mov r0, r0 344 ldr lr, [sp, #S_PC] @ Get PC 345 add sp, sp, #S_FRAME_SIZE 346 /* return & move spsr_svc into cpsr */ 347 subs pc, lr, #4 348 .endm 349 350 .macro get_bad_stack 351 ldr r13, _armboot_start @ setup our mode stack 352 sub r13, r13, #(CONFIG_STACKSIZE) 353 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) 354 /* reserve a couple spots in abort stack */ 355 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) 356 357 str lr, [r13] @ save caller lr / spsr 358 mrs lr, spsr 359 str lr, [r13, #4] 360 361 mov r13, #MODE_SVC @ prepare SVC-Mode 362 @ msr spsr_c, r13 363 msr spsr, r13 364 mov lr, pc 365 movs pc, lr 366 .endm 367 368 .macro get_irq_stack @ setup IRQ stack 369 ldr sp, IRQ_STACK_START 370 .endm 371 372 .macro get_fiq_stack @ setup FIQ stack 373 ldr sp, FIQ_STACK_START 374 .endm 375 376 /* 377 * exception handlers 378 */ 379 .align 5 380 undefined_instruction: 381 get_bad_stack 382 bad_save_user_regs 383 bl do_undefined_instruction 384 385 .align 5 386 software_interrupt: 387 get_bad_stack 388 bad_save_user_regs 389 bl do_software_interrupt 390 391 .align 5 392 prefetch_abort: 393 get_bad_stack 394 bad_save_user_regs 395 bl do_prefetch_abort 396 397 .align 5 398 data_abort: 399 get_bad_stack 400 bad_save_user_regs 401 bl do_data_abort 402 403 .align 5 404 not_used: 405 get_bad_stack 406 bad_save_user_regs 407 bl do_not_used 408 409 #ifdef CONFIG_USE_IRQ 410 411 .align 5 412 irq: 413 get_irq_stack 414 irq_save_user_regs 415 bl do_irq 416 irq_restore_user_regs 417 418 .align 5 419 fiq: 420 get_fiq_stack 421 /* someone ought to write a more effiction fiq_save_user_regs */ 422 irq_save_user_regs 423 bl do_fiq 424 irq_restore_user_regs 425 426 #else 427 428 .align 5 429 irq: 430 get_bad_stack 431 bad_save_user_regs 432 bl do_irq 433 434 .align 5 435 fiq: 436 get_bad_stack 437 bad_save_user_regs 438 bl do_fiq 439 440 #endif
修改后的boot_init.c:
1 #include <common.h> 2 #include <asm/arch/s3c24x0.h> 3 4 #define GSTATUS1 (*(volatile unsigned int *)0x560000B0) 5 #define BUSY 1 6 7 #define NAND_SECTOR_SIZE 512 8 #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1) 9 10 #define NAND_SECTOR_SIZE_LP 2048 11 #define NAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1) 12 13 14 char bLARGEBLOCK; //HJ_add 20090807 15 char b128MB; //HJ_add 20090807 16 17 18 /* 渚涘閮ㄨ皟鐢ㄧ殑鍑芥暟 */ 19 void nand_init_ll(void); 20 int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size); 21 int nand_read_ll_lp(unsigned char *buf, unsigned long start_addr, int size); 22 23 /* NAND Flash鎿嶄綔鐨勬€诲叆鍙? 瀹冧滑灏嗚皟鐢⊿3C2410鎴朣3C2440鐨勭浉搴斿嚱鏁?*/ 24 static void nand_reset(void); 25 static void wait_idle(void); 26 static void nand_select_chip(void); 27 static void nand_deselect_chip(void); 28 static void write_cmd(int cmd); 29 static void write_addr(unsigned int addr); 30 static void write_addr_lp(unsigned int addr); 31 static unsigned char read_data(void); 32 int NF_ReadID(void); //HJ_add 20090807 33 34 /* S3C2440鐨凬AND Flash澶勭悊鍑芥暟 */ 35 static void s3c2440_nand_reset(void); 36 static void s3c2440_wait_idle(void); 37 static void s3c2440_nand_select_chip(void); 38 static void s3c2440_nand_deselect_chip(void); 39 static void s3c2440_write_cmd(int cmd); 40 static void s3c2440_write_addr(unsigned int addr); 41 static void s3c2440_write_addr_lp(unsigned int addr); 42 static unsigned char s3c2440_read_data(void); 43 44 /* S3C2440鐨凬AND Flash鎿嶄綔鍑芥暟 */ 45 46 /* 澶嶄綅 */ 47 static void s3c2440_nand_reset(void) 48 { 49 s3c2440_nand_select_chip(); 50 s3c2440_write_cmd(0xff); // 澶嶄綅鍛戒护 51 s3c2440_wait_idle(); 52 s3c2440_nand_deselect_chip(); 53 } 54 55 /* 绛夊緟NAND Flash灏辩华 */ 56 static void s3c2440_wait_idle(void) 57 { 58 int i; 59 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 60 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT; 61 62 while(!(*p & BUSY)) 63 for(i=0; i<10; i++); 64 } 65 66 /* 鍙戝嚭鐗囬€変俊鍙?*/ 67 static void s3c2440_nand_select_chip(void) 68 { 69 int i; 70 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 71 72 s3c2440nand->NFCONT &= ~(1<<1); 73 for(i=0; i<10; i++); 74 } 75 76 /* 鍙栨秷鐗囬€変俊鍙?*/ 77 static void s3c2440_nand_deselect_chip(void) 78 { 79 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 80 81 s3c2440nand->NFCONT |= (1<<1); 82 } 83 84 /* 鍙戝嚭鍛戒护 */ 85 static void s3c2440_write_cmd(int cmd) 86 { 87 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 88 89 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD; 90 *p = cmd; 91 } 92 93 /* 鍙戝嚭鍦板潃 */ 94 static void s3c2440_write_addr(unsigned int addr) 95 { 96 int i; 97 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 98 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; 99 100 *p = addr & 0xff; 101 for(i=0; i<10; i++); 102 *p = (addr >> 9) & 0xff; 103 for(i=0; i<10; i++); 104 *p = (addr >> 17) & 0xff; 105 for(i=0; i<10; i++); 106 *p = (addr >> 25) & 0xff; 107 for(i=0; i<10; i++); 108 } 109 110 111 /* 鍙戝嚭鍦板潃 */ 112 static void s3c2440_write_addr_lp(unsigned int addr) 113 { 114 int i; 115 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 116 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; 117 int col, page; 118 119 col = addr & NAND_BLOCK_MASK_LP; 120 page = addr / NAND_SECTOR_SIZE_LP; 121 122 *p = col & 0xff; /* Column Address A0~A7 */ 123 for(i=0; i<10; i++); 124 *p = (col >> 8) & 0x0f; /* Column Address A8~A11 */ 125 for(i=0; i<10; i++); 126 *p = page & 0xff; /* Row Address A12~A19 */ 127 for(i=0; i<10; i++); 128 *p = (page >> 8) & 0xff; /* Row Address A20~A27 */ 129 for(i=0; i<10; i++); 130 if (b128MB == 0) 131 *p = (page >> 16) & 0x03; /* Row Address A28~A29 */ 132 for(i=0; i<10; i++); 133 } 134 135 /* 璇诲彇鏁版嵁 */ 136 static unsigned char s3c2440_read_data(void) 137 { 138 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 139 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA; 140 return *p; 141 } 142 143 144 /* 鍦ㄧ涓€娆′娇鐢∟AND Flash鍓嶏紝澶嶄綅涓€涓婲AND Flash */ 145 static void nand_reset(void) 146 { 147 s3c2440_nand_reset(); 148 } 149 150 static void wait_idle(void) 151 { 152 s3c2440_wait_idle(); 153 } 154 155 static void nand_select_chip(void) 156 { 157 int i; 158 159 s3c2440_nand_select_chip(); 160 161 for(i=0; i<10; i++); 162 } 163 164 static void nand_deselect_chip(void) 165 { 166 s3c2440_nand_deselect_chip(); 167 } 168 169 static void write_cmd(int cmd) 170 { 171 s3c2440_write_cmd(cmd); 172 } 173 static void write_addr(unsigned int addr) 174 { 175 s3c2440_write_addr(addr); 176 } 177 178 static void write_addr_lp(unsigned int addr) 179 { 180 s3c2440_write_addr_lp(addr); 181 } 182 183 static unsigned char read_data(void) 184 { 185 return s3c2440_read_data(); 186 } 187 188 /* 鍒濆鍖朜AND Flash */ 189 void nand_init_ll(void) 190 { 191 S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000; 192 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 193 194 #define TACLS 0 195 #define TWRPH0 3 196 #define TWRPH1 0 197 198 /* 璁剧疆鏃跺簭 */ 199 s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); 200 /* 浣胯兘NAND Flash鎺у埗鍣? 鍒濆鍖朎CC, 绂佹鐗囬€?*/ 201 s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0); 202 203 /* 澶嶄綅NAND Flash */ 204 nand_reset(); 205 } 206 #if 1 207 int NF_ReadID(void) 208 { 209 char pMID; 210 char pDID; 211 int nCnt; 212 int nBAddr, nRet; 213 int nBuff; 214 char n4thcycle; 215 int i; 216 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 217 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; 218 219 b128MB = 1; 220 n4thcycle = nBuff = 0; 221 222 nand_init_ll(); 223 nand_select_chip(); 224 s3c2440_write_cmd(0x90); // read id command 225 *p=0x00 & 0xff; 226 for ( i = 0; i < 100; i++ ); 227 228 pMID = s3c2440_read_data(); 229 pDID = s3c2440_read_data(); 230 nBuff = s3c2440_read_data(); 231 n4thcycle = s3c2440_read_data(); 232 233 s3c2440_nand_deselect_chip(); 234 235 if (pDID >= 0xA0) 236 { 237 b128MB = 0; 238 } 239 240 return (pDID); 241 } 242 #endif 243 244 /* 璇诲嚱鏁?*/ 245 int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size) 246 { 247 int i, j; 248 char dat; 249 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 250 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; 251 252 253 if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) 254 { 255 return ; /* 鍦板潃鎴栭暱搴︿笉瀵归綈 */ 256 } 257 258 /* 閫変腑鑺墖 */ 259 nand_select_chip(); 260 261 for(i=start_addr; i < (start_addr + size);) 262 { 263 /* Check Bad Block */ 264 if(0){ 265 /* 鍙戝嚭READ0鍛戒护 */ 266 s3c2440_write_cmd(0x50); 267 268 *p = 5; 269 for(j=0; j<10; j++); 270 *p = (i >> 9) & 0xff; 271 for(j=0; j<10; j++); 272 *p = (i >> 17) & 0xff; 273 for(j=0; j<10; j++); 274 *p = (i >> 25) & 0xff; 275 for(j=0; j<10; j++); 276 s3c2440_wait_idle(); 277 278 dat = s3c2440_read_data(); 279 s3c2440_write_cmd(0); 280 281 /* 鍙栨秷鐗囬€変俊鍙?*/ 282 nand_deselect_chip(); 283 if(dat != 0xff) 284 i += 16384; // 1 Block = 512*32= 16384 285 /* Read Page */ 286 /* 閫変腑鑺墖 */ 287 nand_select_chip(); 288 } 289 /* 鍙戝嚭READ0鍛戒护 */ 290 s3c2440_write_cmd(0); 291 292 /* Write Address */ 293 s3c2440_write_addr(i); 294 s3c2440_wait_idle(); 295 296 for(j=0; j < NAND_SECTOR_SIZE; j++, i++) 297 { 298 *buf = s3c2440_read_data(); 299 buf++; 300 } 301 } 302 303 /* 鍙栨秷鐗囬€変俊鍙?*/ 304 nand_deselect_chip(); 305 306 return 0; 307 } 308 309 /* 璇诲嚱鏁? 310 * Large Page 311 */ 312 int nand_read_ll_lp(unsigned char *buf, unsigned long start_addr, int size) 313 { 314 int i, j; 315 char dat; 316 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 317 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; 318 319 if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) 320 { 321 return ; /* 鍦板潃鎴栭暱搴︿笉瀵归綈 */ 322 } 323 324 /* 閫変腑鑺墖 */ 325 nand_select_chip(); 326 327 for(i=start_addr; i < (start_addr + size);) 328 { 329 /* Check Bad Block */ 330 if(0){ 331 int col, page; 332 333 col = i & NAND_BLOCK_MASK_LP; 334 page = i / NAND_SECTOR_SIZE_LP; 335 /* 鍙戝嚭READ0鍛戒护 */ 336 s3c2440_write_cmd(0x00); 337 338 *p = 5; 339 for(j=0; j<10; j++); 340 *p = 8; 341 for(j=0; j<10; j++); 342 *p = page & 0xff; /* Row Address A12~A19 */ 343 for(j=0; j<10; j++); 344 *p = (page >> 8) & 0xff; /* Row Address A20~A27 */ 345 for(j=0; j<10; j++); 346 if (b128MB == 0) 347 *p = (page >> 16) & 0x03; /* Row Address A28~A29 */ 348 for(j=0; j<10; j++); 349 350 s3c2440_write_cmd(0x30); 351 s3c2440_wait_idle(); 352 353 dat = s3c2440_read_data(); 354 355 /* 鍙栨秷鐗囬€変俊鍙?*/ 356 nand_deselect_chip(); 357 if(dat != 0xff) 358 i += 131072; // 1 Block = 2048*64= 131072 359 /* Read Page */ 360 /* 閫変腑鑺墖 */ 361 nand_select_chip(); 362 } 363 /* 鍙戝嚭READ0鍛戒护 */ 364 write_cmd(0); 365 366 /* Write Address */ 367 write_addr_lp(i); 368 write_cmd(0x30); 369 wait_idle(); 370 371 for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) 372 { 373 *buf = read_data(); 374 buf++; 375 } 376 } 377 378 /* 鍙栨秷鐗囬€変俊鍙?*/ 379 nand_deselect_chip(); 380 381 return 0; 382 } 383 384 int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size) 385 { volatile unsigned long k; 386 /* 鍒濆鍖朜AND Flash */ 387 nand_init_ll(); 388 /* 浠?NAND Flash鍚姩 */ 389 if (NF_ReadID() == 0x76 ){ 390 nand_read_ll(buf, start_addr, (size + NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK)); 391 } else { 392 nand_read_ll_lp(buf, start_addr, (size + NAND_BLOCK_MASK_LP)&~(NAND_BLOCK_MASK_LP)); 393 } 394 return 0; 395 } 396 397 static inline void delay (unsigned long loops) 398 { 399 __asm__ volatile ("1:\n" 400 "subs %0, %1, #1\n" 401 "bne 1b":"=r" (loops):"0" (loops)); 402 } 403 404 /* S3C2440: Mpll = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s) 405 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2 406 */ 407 /* Fin = 12.0000MHz */ 408 #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01)) //HJ 400MHz 409 #define S3C2440_MPLL_405MHZ ((0x7f<<12)|(0x02<<4)|(0x01)) //HJ 405MHz 410 #define S3C2440_MPLL_440MHZ ((0x66<<12)|(0x01<<4)|(0x01)) //HJ 440MHz 411 #define S3C2440_MPLL_480MHZ ((0x98<<12)|(0x02<<4)|(0x01)) //HJ 480MHz 412 #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02)) 413 #define S3C2440_MPLL_100MHZ ((0x5c<<12)|(0x01<<4)|(0x03)) 414 415 #define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02)) //HJ 100MHz 416 417 #define S3C2440_CLKDIV 0x05 /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL */ //HJ 100MHz 418 #define S3C2440_CLKDIV136 0x07 /* FCLK:HCLK:PCLK = 1:3:6, UCLK = UPLL */ //HJ 133MHz 419 #define S3C2440_CLKDIV188 0x04 /* FCLK:HCLK:PCLK = 1:8:8 */ 420 #define S3C2440_CAMDIVN188 ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */ 421 422 /* Fin = 16.9344MHz */ 423 #define S3C2440_MPLL_399MHz ((0x6e<<12)|(0x03<<4)|(0x01)) 424 #define S3C2440_UPLL_48MHZ_Fin16MHz ((60<<12)|(4<<4)|(2)) 425 426 427 /* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s) 428 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2 429 */ 430 #define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00)) 431 #define S3C2410_UPLL_48MHZ ((0x28<<12)|(0x01<<4)|(0x02)) 432 #define S3C2410_CLKDIV 0x03 /* FCLK:HCLK:PCLK = 1:2:4 */ 433 void clock_init(void) 434 { 435 struct s3c24x0_clock_power *clk_power = (struct s3c24x0_clock_power *)0x4C000000; 436 437 /* FCLK:HCLK:PCLK = ?:?:? */ 438 clk_power->CLKDIVN = S3C2440_CLKDIV; //HJ 1:4:8 439 440 /* change to asynchronous bus mod */ 441 __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */ 442 "orr r1, r1, #0xc0000000\n" /* Asynchronous */ 443 "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */ 444 :::"r1" 445 ); 446 447 /* to reduce PLL lock time, adjust the LOCKTIME register */ 448 clk_power->LOCKTIME = 0xFFFFFF; 449 450 /* configure UPLL */ 451 clk_power->UPLLCON = S3C2440_UPLL_48MHZ; //fin=12.000MHz 452 453 /* some delay between MPLL and UPLL */ 454 delay (4000); 455 /* configure MPLL */ 456 clk_power->MPLLCON = S3C2440_MPLL_400MHZ; //fin=12.000MHz 457 /* some delay between MPLL and UPLL */ 458 delay (8000); 459 }
修改后的lowlevel_init.S
1 /* 2 * Memory Setup stuff - taken from blob memsetup.S 3 * 4 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and 5 * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) 6 * 7 * Modified for the Samsung SMDK2410 by 8 * (C) Copyright 2002 9 * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> 10 * 11 * See file CREDITS for list of people who contributed to this 12 * project. 13 * 14 * This program is free software; you can redistribute it and/or 15 * modify it under the terms of the GNU General Public License as 16 * published by the Free Software Foundation; either version 2 of 17 * the License, or (at your option) any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 27 * MA 02111-1307 USA 28 */ 29 30 31 #include <config.h> 32 #include <version.h> 33 34 35 /* some parameters for the board */ 36 37 /* 38 * 39 * Taken from linux/arch/arm/boot/compressed/head-s3c2410.S 40 * 41 * Copyright (C) 2002 Samsung Electronics SW.LEE <hitchcar@sec.samsung.com> 42 * 43 */ 44 45 #define BWSCON 0x48000000 46 47 /* BWSCON */ 48 #define DW8 (0x0) 49 #define DW16 (0x1) 50 #define DW32 (0x2) 51 #define WAIT (0x1<<2) 52 #define UBLB (0x1<<3) 53 54 #define B1_BWSCON (DW16) 55 #define B2_BWSCON (DW16) 56 #define B3_BWSCON (DW16 + WAIT + UBLB) 57 #define B4_BWSCON (DW16) 58 #define B5_BWSCON (DW8) 59 #define B6_BWSCON (DW32) 60 #define B7_BWSCON (DW32) 61 62 /* BANK0CON */ 63 #define B0_Tacs 0x0 /* 0clk */ 64 #define B0_Tcos 0x0 /* 0clk */ 65 #define B0_Tacc 0x7 /* 14clk */ 66 #define B0_Tcoh 0x0 /* 0clk */ 67 #define B0_Tah 0x0 /* 0clk */ 68 #define B0_Tacp 0x0 69 #define B0_PMC 0x0 /* normal */ 70 71 /* BANK1CON */ 72 #define B1_Tacs 0x0 /* 0clk */ 73 #define B1_Tcos 0x0 /* 0clk */ 74 #define B1_Tacc 0x7 /* 14clk */ 75 #define B1_Tcoh 0x0 /* 0clk */ 76 #define B1_Tah 0x0 /* 0clk */ 77 #define B1_Tacp 0x0 78 #define B1_PMC 0x0 79 80 #define B2_Tacs 0x0 81 #define B2_Tcos 0x0 82 #define B2_Tacc 0x7 83 #define B2_Tcoh 0x0 84 #define B2_Tah 0x0 85 #define B2_Tacp 0x0 86 #define B2_PMC 0x0 87 88 #define B3_Tacs 0x0 /* 0clk */ 89 #define B3_Tcos 0x3 /* 4clk */ 90 #define B3_Tacc 0x7 /* 14clk */ 91 #define B3_Tcoh 0x1 /* 1clk */ 92 #define B3_Tah 0x0 /* 0clk */ 93 #define B3_Tacp 0x3 /* 6clk */ 94 #define B3_PMC 0x0 /* normal */ 95 96 #define B4_Tacs 0x0 /* 0clk */ 97 #define B4_Tcos 0x0 /* 0clk */ 98 #define B4_Tacc 0x7 /* 14clk */ 99 #define B4_Tcoh 0x0 /* 0clk */ 100 #define B4_Tah 0x0 /* 0clk */ 101 #define B4_Tacp 0x0 102 #define B4_PMC 0x0 /* normal */ 103 104 #define B5_Tacs 0x0 /* 0clk */ 105 #define B5_Tcos 0x0 /* 0clk */ 106 #define B5_Tacc 0x7 /* 14clk */ 107 #define B5_Tcoh 0x0 /* 0clk */ 108 #define B5_Tah 0x0 /* 0clk */ 109 #define B5_Tacp 0x0 110 #define B5_PMC 0x0 /* normal */ 111 112 #define B6_MT 0x3 /* SDRAM */ 113 #define B6_Trcd 0x1 114 #define B6_SCAN 0x1 /* 9bit */ 115 116 #define B7_MT 0x3 /* SDRAM */ 117 #define B7_Trcd 0x1 /* 3clk */ 118 #define B7_SCAN 0x1 /* 9bit */ 119 120 /* REFRESH parameter */ 121 #define REFEN 0x1 /* Refresh enable */ 122 #define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */ 123 #define Trp 0x0 /* 2clk */ 124 #define Trc 0x3 /* 7clk */ 125 #define Tchr 0x2 /* 3clk */ 126 #define REFCNT 0x4F4 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */ 127 /**************************************/ 128 129 _TEXT_BASE: 130 .word TEXT_BASE 131 132 .globl lowlevel_init 133 lowlevel_init: 134 /* memory control configuration */ 135 /* make r0 relative the current location so that it */ 136 /* reads SMRDATA out of FLASH rather than memory ! */ 137 138 ldr r0, =SMRDATA 139 ldr r1, _TEXT_BASE 140 sub r0, r0, r1 141 ldr r1, =BWSCON /* Bus Width Status Controller */ 142 add r2, r0, #13*4 143 144 0: 145 ldr r3, [r0], #4 146 str r3, [r1], #4 147 cmp r2, r0 148 bne 0b 149 150 /* everything is fine now */ 151 mov pc, lr 152 153 .ltorg 154 /* the literal pools origin */ 155 156 SMRDATA: 157 .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) 158 .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) 159 .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) 160 .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) 161 .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) 162 .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) 163 .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) 164 .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) 165 .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) 166 .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) 167 .word 0x32 168 .word 0x30 169 .word 0x30
修改后的speed.c
1 /* 2 * (C) Copyright 2001-2004 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * (C) Copyright 2002 6 * David Mueller, ELSOFT AG, d.mueller@elsoft.ch 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 */ 26 27 /* This code should work for both the S3C2400 and the S3C2410 28 * as they seem to have the same PLL and clock machinery inside. 29 * The different address mapping is handled by the s3c24xx.h files below. 30 */ 31 32 #include <common.h> 33 #ifdef CONFIG_S3C24X0 34 35 #include <asm/io.h> 36 #include <asm/arch/s3c24x0_cpu.h> 37 38 #define MPLL 0 39 #define UPLL 1 40 41 /* ------------------------------------------------------------------------- */ 42 /* NOTE: This describes the proper use of this file. 43 * 44 * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. 45 * 46 * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of 47 * the specified bus in HZ. 48 */ 49 /* ------------------------------------------------------------------------- */ 50 51 static ulong get_PLLCLK(int pllreg) 52 { 53 struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); 54 ulong r, m, p, s; 55 56 if (pllreg == MPLL) 57 r = readl(&clk_power->MPLLCON); 58 else if (pllreg == UPLL) 59 r = readl(&clk_power->UPLLCON); 60 else 61 hang(); 62 63 m = ((r & 0xFF000) >> 12) + 8; 64 p = ((r & 0x003F0) >> 4) + 2; 65 s = r & 0x3; 66 67 return (CONFIG_SYS_CLK_FREQ * m*2) / (p << s); 68 } 69 70 /* return FCLK frequency */ 71 ulong get_FCLK(void) 72 { 73 return get_PLLCLK(MPLL); 74 } 75 76 /* return HCLK frequency */ 77 ulong get_HCLK(void) 78 { 79 struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); 80 81 //return (readl(&clk_power->CLKDIVN) & 2) ? get_FCLK() / 2 : get_FCLK(); 82 return (get_FCLK()/4); 83 } 84 85 /* return PCLK frequency */ 86 ulong get_PCLK(void) 87 { 88 struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); 89 90 return (readl(&clk_power->CLKDIVN) & 1) ? get_HCLK() / 2 : get_HCLK(); 91 } 92 93 /* return UCLK frequency */ 94 ulong get_UCLK(void) 95 { 96 return get_PLLCLK(UPLL); 97 } 98 99 #endif /* CONFIG_S3C24X0 */
TQ2440开发板移植UBOOT-2010.06总结(2),布布扣,bubuko.com
原文:http://www.cnblogs.com/Ilmen/p/3577586.html