Chinaunix首页 | 论坛 | 博客
  • 博客访问: 179719
  • 博文数量: 31
  • 博客积分: 471
  • 博客等级: 下士
  • 技术积分: 240
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-07 12:53
文章分类

全部博文(31)

文章存档

2015年(1)

2013年(1)

2012年(1)

2011年(28)

分类: LINUX

2011-08-17 14:46:42

上接:《2 norflash驱动移植

http://blog.chinaunix.net/space.php?uid=24473044&do=blog&id=1762712

3 添加nand flash支持

参考说明

1本文参考了singleboy

2参考了Tekkaman Ninjablog文章http://blog.chinaunix.net/space.php?uid=20543672&do=blog&cuid=2085154

3)参考了黄刚的blog

http://blogold.chinaunix.net:80/u3/101649/showart.php?id=2276917

向上述作者表示感谢!

一、移植环境说明

1,主机环境:VMWareRHEL5

 

2,编译器:arm-linux-gcc v4.4.3

 

3,开发板:mini24402M nor flash256M nand flash(自改,原64M),NEC屏;

 

4u-boot版本:u-boot-2009.08

 

二、移植任务描述

实现ubootnand flash256M)上启动。

 

三、移植步骤

3.1Nand flashNor flash双启动原理

 

首先,看一下我们熟悉的u-boot启动的时候执行的一段程序,这段程序一般存放在Nand flash中或Nor flash中。我们所说的Nand flash启动或Nor flash启动主要是涉及到一段搬移代码。这段搬移代码的功能是u-boot自己把自己搬移到内存中执行。如下是Nor flash启动中的这段搬移代码(这里以s3c2410为例)

 

  relocate:                        /* relocate U-Boot to RAM */

  adr r0, _start        /* r0 <- current position of code */

  ldr r1, _TEXT_BASE        /* test if we run from flash or RAM */

  cmp r0, r1                        /* don't reloc during debug */

  beq stack_setup

  ldr r2, _armboot_start

  ldr r3, _bss_start

  sub r2, r3, r2                /* r2 <- size of armboot */

  add r2, r0, r2                /* r2 <- source end address */

  copy_loop:

  ldmia r0!, {r3-r10}                /* copy from source address [r0] */

  stmia r1!, {r3-r10}                /* copy to target address [r1] */

  cmp r0, r2                /* until source end addreee [r2] */

  ble copy_loop

  #endif        /* CONFIG_SKIP_RELOCATE_UBOOT */

  #endif

 

上面这段代码就是把u-boot搬移到内存。而不同的启动方式区别也就在这段代码上,如果我们这里是Nand flash启动的话我们也需要写相同功能的代码,不同的是对于Nand的操作和Nor的操作是完全不同的,选择Nor flash启动是将Nor flash映射到片选0上也就是0x0地址而选择Nand flash启动则是将CPU的片内RAM(4K)映射到0地址,通过Nand flash控制器操作Nand flash。我们这里讨论如何实现Nand Nor双启动。下面我们看看这两种启动的映射关系。

 

同时我们可以看到: 总线宽度和等待控制寄存器:

在系统重启时会扫描BWSCON的状态,而BWSCON的其他位的初始状态都是0,只有DW0(BWSCON[2:1])的值由OM[1:0]来决定,通过上面的2个图我们可以发现,我们可以通过判断BWSCON的第2位、第3{DW0BWSCON[2:1])}的值,判断是Nor flash启动还是Nand Flash启动。可以启动代码之前添加如下代码,来判断是Nor flash启动还是Nand Flash启动。

 

 # define BWSCON   0x48000000

        ldr r0,=BWSCON

        ldr r0,[r0]

        and r0,r0,#6

        cmp  r0, #0 

        bne  relocate

 

 

 ///////////////////////////////////////////////////

     //nand_boot

  //Nand 搬移代码

////////////////////////////////////////////////////

  relocate

       //nor_boot

      //Nor 搬移代码

////////////////////////////////////////////////////

有了上面这段代码,就可以实现双启动了,只要再适当的添加对应的功能我们的uboot就完成了。

 

3.2,为u-boot增加对nand flash支持实际操作

 

1】修改代码重定向部分,增加Nor flash Nand flash 双启动

修改cpu/arm920t/start.S文件,为使u-bootNand Flash启动,需要将下面注释掉的CPUDRAM初始化部分还原。

 

gedit cpu/arm920t/start.S,定位到199行附近,找到如下代码

 

//#ifndef CONFIG_SKIP_LOWLEVEL_INIT

 //bl cpu_init_crit

//#endif

 

将注释掉的这段代码恢复,修改如下:

 

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

 bl cpu_init_crit

#endif

 

Tekkaman Ninja2009.08 开始就在启动时增加了启动时检测自身是否已经在SDRAM(通过OpenJTAG载入),以及芯片是Norboot还是Nandboot的机制,来决定代码重定向的方式,使得编译出的bin文件可以同时烧入Nand FlashNor flash,以及被OpenJTAG载入进行调试。至于这部分的原理,在Tekkaman Ninja的博客文章《在U-boot下实现自动识别启动Flash的原理(针对S3C24x0)》中有详细叙述。这部分代码修改后结果如下:

 

(1)判断当前代码位置,如果在内存,直接跳到stack_setup

206

//#ifndef CONFIG_SKIP_RELOCATE_UBOOT

//relocate: /* relocate U-Boot to RAM */

/***************** Check the code position begain*******************************/

 adr r0, _start  /* r0 <- current position of code   */

 ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */

 cmp     r0, r1          /* don't reloc during debug  */

 beq     stack_setup

/****************** Check the code position end ********************************/

 

(2)如果不是在代码当前位置不再内存中,就判断启动的FlashNand 或者Nor

/***************** Check the boot flash begain **********************************/

# define BWSCON  0x48000000

        ldr r0,=BWSCON

        ldr r0,[r0]

        ands r0,r0,#6

        cmp  r0, #0 

        bne  relocate

#if 0

//tekkaman

 ldr r1, =( (4<<28)|(3<<4)|(3<<2) )  /* address of Internal SRAM  0x4000003C*/

 mov r0, #0  /* r0 = 0 */

 str r0, [r1]

 

 mov r1, #0x3c  /* address of men  0x0000003C*/

 ldr r0, [r1]

 cmp r0, #0

 bne relocate

#endif

 /* recovery  */

 ldr r0, =(0xdeadbeef)

 ldr r1, =( (4<<28)|(3<<4)|(3<<2) )

 str r0, [r1]

/***************** check the boot flash end ************************************/

(3)如果判断是在Nand Flash中启动的话,那么nand  Flash搬移代码如下:

定义u-bootnand flash中存放的长度为#define LENGTH_UBOOT 0x60000,可以方便修改u-boot因为裁剪和增添大小的改变而占的长度。

 

// copy U-Boot to RAM from Nand Flash

 

/***************** NAND BOOT start *************************************************/

 

#define LENGTH_UBOOT 0x60000

#define NAND_CTL_BASE 0x4E000000

 

#ifdef CONFIG_S3C2440

/* Offset */

#define oNFCONF 0x00

#define oNFCONT 0x04

#define oNFCMD 0x08

#define oNFSTAT 0x20

 

 @ reset NAND

 mov r1, #NAND_CTL_BASE

 ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )

 str r2, [r1, #oNFCONF]

 ldr r2, [r1, #oNFCONF]

 

 ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control

 str r2, [r1, #oNFCONT]

 ldr r2, [r1, #oNFCONT]

 

 ldr r2, =(0x6) @ RnB Clear

 str r2, [r1, #oNFSTAT]

 ldr r2, [r1, #oNFSTAT]

 

 mov r2, #0xff @ RESET command

 strb r2, [r1, #oNFCMD]

 

 mov r3, #0 @ wait

nand1:

 add r3, r3, #0x1

 cmp r3, #0xa

 blt nand1

 

nand2:

 ldr r2, [r1, #oNFSTAT] @ wait ready

 tst r2, #0x4

 beq nand2

 

 

 ldr r2, [r1, #oNFCONT]

 orr r2, r2, #0x2 @ Flash Memory Chip Disable

 str r2, [r1, #oNFCONT]

 

 @ get read to call C functions (for nand_read())

 ldr sp, DW_STACK_START @ setup stack pointer

 mov fp, #0 @ no previous frame, so fp=0

 

 @ copy U-Boot to RAM

 ldr r0, =TEXT_BASE

 mov r1, #0x0

 mov r2, #LENGTH_UBOOT

 bl nand_read_ll

 tst r0, #0x0

 beq ok_nand_read

 

bad_nand_read:

loop2:

 b loop2 @ infinite loop

ok_nand_read:

 @ verify

 mov r0, #0

 ldr r1, =TEXT_BASE

 mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes

go_next:

 ldr r3, [r0], #4

 ldr r4, [r1], #4

 teq r3, r4

 bne notmatch

 subs r2, r2, #4

 beq stack_setup

 bne go_next

 

notmatch:

loop3:

 b loop3 @ infinite loop

#endif

 

#ifdef CONFIG_S3C2410

 

/* Offset */

#define oNFCONF 0x00

#define oNFCMD 0x04

#define oNFSTAT 0x10

 

 @ reset NAND

 mov r1, #NAND_CTL_BASE

 ldr r2, =0xf830 @ initial value

 str r2, [r1, #oNFCONF]

 ldr r2, [r1, #oNFCONF]

 bic r2, r2, #0x800 @ enable chip

 str r2, [r1, #oNFCONF]

 mov r2, #0xff  @ RESET command

 strb r2, [r1, #oNFCMD]

 

 

 mov r3, #0 @ wait

nand1:

 add r3, r3, #0x1

 cmp r3, #0xa

 blt nand1

 

nand2:

 ldr r2, [r1, #oNFSTAT] @ wait ready

 tst r2, #0x1

 beq nand2

 

 ldr r2, [r1, #oNFCONF]

 orr r2, r2, #0x800 @ disable chip

 str r2, [r1, #oNFCONF]

 

 @ get read to call C functions (for nand_read())

 ldr sp, DW_STACK_START @ setup stack pointer

 mov fp, #0 @ no previous frame, so fp=0

 

 @ copy U-Boot to RAM

 ldr r0, =TEXT_BASE

 mov r1, #0x0

 mov r2, #LENGTH_UBOOT

 bl nand_read_ll

 tst r0, #0x0

 beq ok_nand_read

 

bad_nand_read:

loop2:

 b loop2 @ infinite loop

 

 

ok_nand_read:

 @ verify

 mov r0, #0

 ldr r1, =TEXT_BASE

 mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes

go_next:

 ldr r3, [r0], #4

 ldr r4, [r1], #4

 teq r3, r4

 bne notmatch

 subs r2, r2, #4

 beq stack_setup

 bne go_next

 

notmatch:

loop3:

 b loop3 @ infinite loop

 

#endif

/***************** NAND BOOT end *************************************************/

 

 

(4)如果判断是在Nor  Flash中启动的话那么nor  Flash搬移代码如下

 

// copy U-Boot to RAM  form   Nor  Flash

 

/***************** NOR BOOT start *************************************************/

relocate:    /* relocate U-Boot to RAM     */

      /*********** CHECK_FOR_MAGIC_NUMBER***************/

 ldr r1, =(0xdeadbeef)

 cmp r0, r1

 bne loop3

      /*********** CHECK_FOR_MAGIC_NUMBER***************/

 adr r0, _start  /* r0 <- current position of code   */

 ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */

 ldr r2, _armboot_start

 ldr r3, _bss_start

 sub r2, r3, r2  /* r2 <- size of armboot            */

 add r2, r0, r2  /* r2 <- source end address         */

 

copy_loop:

 ldmia r0!, {r3-r10}  /* copy from source address [r0]    */

 stmia r1!, {r3-r10}  /* copy to   target address [r1]    */

 cmp r0, r2   /* until source end addreee [r2]    */

 ble copy_loop

//#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

/***************** NOR BOOT end********************************************/

 

 /* Set up the stack          */

stack_setup:

... ...

 

2】在上面添加的代码中有一个跳转:bl nand_read_ll ,它跳入是新增的C 语言文件board/gy/mini2440/nand_read.c中的函数,这个文件原本是用vivi 的代码,后来经过openmoko 的修改,并支持不同的Nand Flash 芯片,我又这里多加了几个个芯片ID以支持所有mini2440 Nand Flash。代码如下:

 

/*

 * nand_read.c: Simple NAND read functions for booting from NAND

 *

 * This is used by cpu/arm920/start.S assembler code,

 * and the board-specific linker script must make sure this

 * file is linked within the first 4kB of NAND flash.

 *

 * Taken from GPLv2 licensed vivi bootloader,

 * Copyright (C) 2002 MIZI Research, Inc.

 *

 * Author: Hwang, Chideok

 * Date  : $Date: 2004/02/04 10:37:37 $

 *

 * u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.

 * Author: Harald Welte

 */

 

#include

#include

 

 

#define __REGb(x) (*(volatile unsigned char *)(x))

#define __REGw(x) (*(volatile unsigned short *)(x))

#define __REGi(x) (*(volatile unsigned int *)(x))

#define NF_BASE  0x4e000000

#if defined(CONFIG_S3C2410)

#define NFCONF  __REGi(NF_BASE + 0x0)

#define NFCMD  __REGb(NF_BASE + 0x4)

#define NFADDR  __REGb(NF_BASE + 0x8)

#define NFDATA  __REGb(NF_BASE + 0xc)

#define NFSTAT  __REGb(NF_BASE + 0x10)

#define NFSTAT_BUSY 1

#define nand_select() (NFCONF &= ~0x800)

#define nand_deselect() (NFCONF |= 0x800)

#define nand_clear_RnB() do {} while (0)

#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)

#define NFCONF  __REGi(NF_BASE + 0x0)

#define NFCONT  __REGi(NF_BASE + 0x4)

#define NFCMD  __REGb(NF_BASE + 0x8)

#define NFADDR  __REGb(NF_BASE + 0xc)

#define NFDATA  __REGb(NF_BASE + 0x10)

#define NFDATA16 __REGw(NF_BASE + 0x10)

#define NFSTAT  __REGb(NF_BASE + 0x20)

#define NFSTAT_BUSY 1

#define nand_select() (NFCONT &= ~(1 << 1))

#define nand_deselect() (NFCONT |= (1 << 1))

#define nand_clear_RnB() (NFSTAT |= (1 << 2))

#endif

 

static inline void nand_wait(void)

{

 int i;

 

 while (!(NFSTAT & NFSTAT_BUSY))

  for (i=0; i<10; i++);

}

 

struct boot_nand_t {

 int page_size;

 int block_size;

 int bad_block_offset;

// unsigned long size;

};

 

#if 0

#if defined(CONFIG_S3C2410) || defined(CONFIG_MINI2440)

/* configuration for 2410 with 512byte sized flash */

#define NAND_PAGE_SIZE  512

#define BAD_BLOCK_OFFSET 5

#define NAND_BLOCK_MASK  (NAND_PAGE_SIZE - 1)

#define NAND_BLOCK_SIZE  0x4000

#else

/* configuration for 2440 with 2048byte sized flash */

#define NAND_5_ADDR_CYCLE

#define NAND_PAGE_SIZE  2048

#define BAD_BLOCK_OFFSET NAND_PAGE_SIZE

#define NAND_BLOCK_MASK  (NAND_PAGE_SIZE - 1)

#define NAND_BLOCK_SIZE  (NAND_PAGE_SIZE * 128)//256M nandflash *128,128M nandflash *64

#endif

 

/* compile time failure in case of an invalid configuration */

#if defined(CONFIG_S3C2410) && (NAND_PAGE_SIZE != 512)

#error "S3C2410 does not support nand page size != 512"

#endif

#endif

 

static int is_bad_block(struct boot_nand_t * nand, unsigned long i)

{

 unsigned char data;

 unsigned long page_num;

 

 nand_clear_RnB();

 if (nand->page_size == 512) {

  NFCMD = NAND_CMD_READOOB; /* 0x50 */

  NFADDR = nand->bad_block_offset & 0xf;

  NFADDR = (i >> 9) & 0xff;

  NFADDR = (i >> 17) & 0xff;

  NFADDR = (i >> 25) & 0xff;

 } else if (nand->page_size == 2048) {

  page_num = i >> 11; /* addr / 2048 */

  NFCMD = NAND_CMD_READ0;

  NFADDR = nand->bad_block_offset & 0xff;

  NFADDR = (nand->bad_block_offset >> 8) & 0xff;

  NFADDR = page_num & 0xff;

  NFADDR = (page_num >> 8) & 0xff;

  NFADDR = (page_num >> 16) & 0xff;

  NFCMD = NAND_CMD_READSTART;

 } else {

  return -1;

 }

 nand_wait();

 data = (NFDATA & 0xff);

 if (data != 0xff)

  return 1;

 

 return 0;

}

 

static int nand_read_page_ll(struct boot_nand_t * nand, unsigned char *buf, unsigned long addr)

{

 unsigned short *ptr16 = (unsigned short *)buf;

 unsigned int i, page_num;

 

 nand_clear_RnB();

 

 NFCMD = NAND_CMD_READ0;

 

 if (nand->page_size == 512) {

  /* Write Address */

  NFADDR = addr & 0xff;

  NFADDR = (addr >> 9) & 0xff;

  NFADDR = (addr >> 17) & 0xff;

  NFADDR = (addr >> 25) & 0xff;

 } else if (nand->page_size == 2048) {

  page_num = addr >> 11; /* addr / 2048 */

  /* Write Address */

  NFADDR = 0;

  NFADDR = 0;

  NFADDR = page_num & 0xff;

  NFADDR = (page_num >> 8) & 0xff;

  NFADDR = (page_num >> 16) & 0xff;

  NFCMD = NAND_CMD_READSTART;

 } else {

  return -1;

 }

 nand_wait();

 

#if defined(CONFIG_S3C2410)

 for (i = 0; i < nand->page_size; i++) {

  *buf = (NFDATA & 0xff);

  buf++;

 }

#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)

 for (i = 0; i < (nand->page_size>>1); i++) {

  *ptr16 = NFDATA16;

  ptr16++;

 }

#endif

 

 return nand->page_size;

}

 

static unsigned short nand_read_id(void)

{

 unsigned short res = 0;

 NFCMD = NAND_CMD_READID;

 NFADDR = 0;

 res = NFDATA;

 res = (res << 8) | NFDATA;

 return res;

}

 

extern unsigned int dynpart_size[];

 

/* low level nand read function */

int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)

{

 int i, j;

 unsigned short nand_id;

 struct boot_nand_t nand;

 

 /* chip Enable */

 nand_select();

 nand_clear_RnB();

 

 for (i = 0; i < 10; i++)

  ;

 nand_id = nand_read_id();

 if (0) { /* dirty little hack to detect if nand id is misread */

  unsigned short * nid = (unsigned short *)0x31fffff0;

  *nid = nand_id;

 }

 

       if (nand_id == 0xec76   /* Samsung K91208 */

           ||nand_id == 0xad76 ) { /*Hynix HY27US08121A*/

  nand.page_size = 512;

  nand.block_size = 16 * 1024;

  nand.bad_block_offset = 5;

 // nand.size = 0x4000000;

 } else if (nand_id == 0xecf1  /* Samsung K9F1G08U0B */

     ||nand_id == 0xecda  /* Samsung K9F2G08U0B */

     ||nand_id == 0xecd3 ) { /* Samsung K9K8G08 */

  nand.page_size = 2048;

  nand.block_size = 128 * 1024;

  nand.bad_block_offset = nand.page_size;

 // nand.size = 0x8000000;

 } else {

  return -1; // hang

 }

 if ((start_addr & (nand.block_size-1)) || (size & ((nand.block_size-1))))

  return -1; /* invalid alignment */

 

 for (i=start_addr; i < (start_addr + size);) {

#ifdef CONFIG_S3C2410_NAND_SKIP_BAD

 //if (i & (nand.block_size-1)== 0) {//warning: suggest parentheses around comparison in operand of '&'

 if ((i & (nand.block_size-1))== 0) {    

 

  if (is_bad_block(&nand, i) ||

       is_bad_block(&nand, i + nand.page_size)) {

    /* Bad block */

    i += nand.block_size;

    size += nand.block_size;

    continue;

   }

  }

#endif

  j = nand_read_page_ll(&nand, buf, i);

  i += j;

  buf += j;

 }

 

 /* chip Disable */

 nand_deselect();

 

 return 0;

}

 

然后保存为nand_read.c,还要记得路径是在board/gy/mini2440/目录下。

3gedit board/gy/mini2440/Makefile 28行添加nand_read.c的编译选项,使他编译到u-boot中,修改后代码如下:

 

include $(TOPDIR)/config.mk

LIB = $(obj)lib$(BOARD).a

COBJS :=  nand_read.o mini2440.o flash.o

SOBJS := lowlevel_init.o

4】在mini2440.h头文件中加入Nand要用到的宏和寄存器的定义。

gedit include/configs/mini2440.h头文件,定位43行,加入下列代码:

/*-----------------------------------------------------------------------

 * NAND flash settings

 */

 

#define CONFIG_S3C2410_NAND_SKIP_BAD 1

 

5】在cpu/arm920t/u-boot.lds中添加下面两行代码,主要目的是防止编译器把我们自己添加的用于nandboot的子函数放到4K之后,否则是无法启动的,修改后代码如下:

gedit cpu/arm920t/u-boot.lds

 .text :

 {

     cpu/arm920t/start.o (.text)

     board/gy/mini2440/lowlevel_init.o (.text)

     board/gy/mini2440/nand_read.o (.text)

     *(.text)

 }

 

3.3,在U-boot 启动的第一阶段,初始化了Nand Flash 控制器。但到第二阶段start_armboot函数还是会再次初始化Nand Flash 控制器。因为第二阶段和第一阶段的代码基本是独立的,第一阶段的代码基本只起到代码重定位的作用,到了第二阶段才是真正U-boot 的开始,以前的初始化过程还会重做一遍,比如始化Nand Flash 控制器、CPU 频率等。因为 S3C2440 S3C2410 之间的很大差别就是:S3C2410 Nand Flash 控制器只支持512B+16B Nand Flash,而S3C2440 还支持2KB+64B 的大容量Nand Flash所以在Nand Flash 控制器上寄存器和控制流程上的差别很明显,底层驱动代码的修改也是必须的。具体的差别还是需要对比芯片数据手册的,下面我们结合代码来分析一下u-boot在第二阶段的执行流程:

<1>lib_arm/board.c文件中的start_armboot函数调用了drivers/mtd/nand/nand.c文件中的nand_init函数,如下:

  #if defined(CONFIG_CMD_NAND) //可以看到CONFIG_CMD_NAND宏决定了Nand的初始化

      puts ("NAND: ");

      nand_init();

  #endif

<2>nand_init调用了同文件下的nand_init_chip函数;

<3>nand_init_chip函数调用drivers/mtd/nand/s3c2410_nand.c文件下的board_nand_init函数,然后再调用drivers/mtd/nand/nand_base.c函数中的nand_scan函数;

<4>nand_scan函数调用了同文件下的nand_scan_ident函数等。

 

1Nand Flash 相关代码的修改

gedit drivers/mtd/nand/s3c2410_nand.c,定位到37行,修改如下:

#define __REGb(x) (*(volatile unsigned char *)(x))

#define __REGi(x) (*(volatile unsigned int *)(x))

#define NF_BASE  0x4e000000

#if defined(CONFIG_S3C2410)

#define NFCONF  __REGi(NF_BASE + 0x0)

#define NFCMD  __REGb(NF_BASE + 0x4)

... ...

#define S3C2410_ADDR_NALE 4

#define S3C2410_ADDR_NCLE 8

#endif

#if defined(CONFIG_S3C2440)

#define S3C2410_ADDR_NALE 0x08

#define S3C2410_ADDR_NCLE 0x0c

 

#define NFCONF  __REGi(NF_BASE + 0x0)

#define NFCONT    __REGb(NF_BASE + 0x4)  

#define NFCMD  __REGb(NF_BASE + 0x8)

#define NFADDR  __REGb(NF_BASE + 0xc)

#define NFDATA  __REGb(NF_BASE + 0x10)

 

#define NFMECCD0   __REGb(NF_BASE + 0x14)

#define NFMECCD1   __REGb(NF_BASE + 0x18)

#define NFSECCD   __REGb(NF_BASE + 0x1c)

#define NFSTAT  __REGb(NF_BASE + 0x20)

#define NFESTAT0 __REGb(NF_BASE + 0x24)

#define NFESTAT1 __REGb(NF_BASE + 0x28)

#define NFMECC0  __REGb(NF_BASE + 0x2c)

#define NFMECC1  __REGb(NF_BASE + 0x30)

#define NFSECC  __REGb(NF_BASE + 0x34)

#define NFSBLK  __REGb(NF_BASE + 0x38)

#define NFEBLK  __REGb(NF_BASE + 0x3c)

#define NFECC0  __REGb(NF_BASE + 0x2c)

#define NFECC1  __REGb(NF_BASE + 0x2d)

#define NFECC2  __REGb(NF_BASE + 0x2e)

#define S3C2410_NFCONT_EN          (1<<0)

#define S3C2410_NFCONT_INITECC     (1<<4)

#define S3C2410_NFCONT_nFCE        (1<<1)

#define S3C2410_NFCONT_MAINECCLOCK (1<<5)

#define S3C2410_NFCONF_TACLS(x)    ((x)<<12)

#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<8)

#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<4)

#endif

ulong IO_ADDR_W = NF_BASE; 

static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)

{

 struct nand_chip *chip = mtd->priv;

DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);

 if (ctrl & NAND_CTRL_CHANGE) {

  //ulong IO_ADDR_W = NF_BASE;//应注释掉这个局部变量否则找不到ID "No NAND device found!!!"

   IO_ADDR_W = NF_BASE;

 if (!(ctrl & NAND_CLE))      //要写的是地址

   IO_ADDR_W |= S3C2410_ADDR_NCLE;

  if (!(ctrl & NAND_ALE))  //要写的是命令

   IO_ADDR_W |= S3C2410_ADDR_NALE;

  //chip->IO_ADDR_W = (void *)IO_ADDR_W;

#if defined(CONFIG_S3C2410)

  if (ctrl & NAND_NCE)

   NFCONF &= ~S3C2410_NFCONF_nFCE; //使能nand flash

  else

   NFCONF |= S3C2410_NFCONF_nFCE; //禁止nand flash

#endif

#if defined(CONFIG_S3C2440)

  if (ctrl & NAND_NCE)

   NFCONT &= ~S3C2410_NFCONT_nFCE;

  else

   NFCONT |= S3C2410_NFCONT_nFCE;

#endif

 }

 if (cmd != NAND_CMD_NONE)

  //writeb(cmd, chip->IO_ADDR_W);

  writeb(cmd, (void *)IO_ADDR_W);

}

... ...

#ifdef CONFIG_S3C2410_NAND_HWECC

void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)

{

 DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);

#if defined(CONFIG_S3C2410)

 NFCONF |= S3C2410_NFCONF_INITECC;

#endif

#if defined(CONFIG_S3C2440)

 NFCONT |= S3C2410_NFCONT_INITECC;

#endif

}

... ...

#endif

int board_nand_init(struct nand_chip *nand)

{

 u_int32_t cfg;

 u_int8_t tacls, twrph0, twrph1;

 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

 DEBUGN("board_nand_init()\n");

 clk_power->CLKCON |= (1 << 4);

 /* initialize hardware */

#if defined(CONFIG_S3C2410)

  twrph0 = 3; twrph1 = 0; tacls = 0;

  cfg = S3C2410_NFCONF_EN;

  cfg |= S3C2410_NFCONF_TACLS(tacls - 1);

  cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);

  cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);

  NFCONF = cfg;

 /* initialize nand_chip data structure */

 nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e00000c;

#endif

#if defined(CONFIG_S3C2440)

  twrph0 = 4; twrph1 = 2; tacls = 0;

  cfg = 0;

  cfg |= S3C2410_NFCONF_TACLS(tacls - 1);

  cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);

  cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);

  NFCONF = cfg;

  NFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(0<<1)|(1<<0);

  /* initialize nand_chip data structure */

  nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;

#endif

 /* read_buf and write_buf are default */

 /* read_byte and write_byte are default */

 

 

2】在mini2440.h里添加nand_flash相关宏定义

gedit include/configs/mini2440.h,定位到101行附近,加入下列代码:

/*

 * Command line configuration.

 */

#include

#define CONFIG_CMD_CACHE

#define CONFIG_CMD_DATE

#define CONFIG_CMD_ELF

#define CONFIG_CMD_NAND

... ...

 

定位到193行附近,注释掉下列代码:

 

/* timeout values are in ticks */

#define CONFIG_SYS_FLASH_ERASE_TOUT (5*CONFIG_SYS_HZ) /* Timeout for Flash Erase */

#define CONFIG_SYS_FLASH_WRITE_TOUT (5*CONFIG_SYS_HZ) /* Timeout for Flash Write */

 

//#define CONFIG_ENV_IS_IN_FLASH 1

//#define CONFIG_ENV_SIZE  0x20000 /* Total Size of Environment Sector */

 

然后加入下列代码:

 

/*-----------------------------------------------------------------------

 * NAND flash settings

 */

#define CONFIG_ENV_IS_IN_NAND  1

#define CONFIG_ENV_OFFSET      0x40000 //将环境变量保存到nand中的0x40000位置必,须在块的起始位置

#define CONFIG_ENV_SIZE        0x20000 /*必须为块大小的整数倍 否则会提示下面的信息,将擦除整个块*/

#if defined(CONFIG_CMD_NAND)

 

 

在文件199行附近加入下列代码:

/*-----------------------------------------------------------------------

 * NAND flash settings

 */

#if defined(CONFIG_CMD_NAND)

#define CONFIG_NAND_S3C2410

#define CONFIG_SYS_NAND_BASE 0x4E000000

#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices  */

#define SECTORSIZE 512

#define SECTORSIZE_2K 2048

#define NAND_SECTOR_SIZE SECTORSIZE

#define NAND_SECTOR_SIZE_2K SECTORSIZE_2K

#define NAND_BLOCK_MASK 511

#define NAND_BLOCK_MASK_2K 2047

#define NAND_MAX_CHIPS 1

#define CONFIG_MTD_NAND_VERIFY_WRITE

#define CONFIG_SYS_64BIT_VSPRINTF  /* needed for nand_util.c */

#endif /* CONFIG_CMD_NAND */

#endif     /* __CONFIG_H */

 

 

然后保存,重新编译、拨到nor 档下载,在拨到nand 档上电运行:

 

U-Boot 2009.08 (Jul 29 2011 - 20:53:56)

 

 modified by gy (robinfit01@163.com)

 Love  pore and Linux forever!!!

 

DRAM:  64 MB

Flash:  2 MB

NAND:  256 MiB

In:    serial

Out:   serial

Err:   serial

[mini2440] #

 

接下来将为u-boot-2009.08-22增加网卡DM9000驱动支持(未完持续)

 

 

 

 

 

阅读(2067) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~