TQ2440开发板移植UBOOT-2010.06总结(2)

一. 代码修改 

     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;
View Code

      删除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
View Code

      修改后的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 }
View Code

     修改后的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
View Code

    修改后的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 */
View Code

 

 

转载于:https://www.cnblogs.com/Ilmen/p/3577586.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值