Chinaunix首页 | 论坛 | 博客
  • 博客访问: 152507
  • 博文数量: 22
  • 博客积分: 1456
  • 博客等级: 上尉
  • 技术积分: 252
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-25 00:08
个人简介

ddd

文章存档

2011年(1)

2010年(21)

我的朋友

分类: 嵌入式

2010-06-03 18:38:23

移植U-Boot-2010.03到友善之臂mini2440(三)

3.1  board/mini2440/目录下加入NAND Flash读取函数(start.S中需要的nand_read_ll函数)文件nand_read.c,新建board/mini2440/nand_read.c,这里的开发板使用的是128MB ,大页的读写。下面是nand_read.c文件的内容。(注意和小页的NandFlash的不同)

 

board/mini2440/nand_read.c

 

/*

 * 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 * 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()

{

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

              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;

}

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

3.2修改board/mini2440/Makefile文件,28,nand_read.c编译进u-boot

 

OBJS := mini2440.o nand_read.o flash.o

 

3.3修改board/mini2440/lowlevel_init.S文件

(1)修改 REFRESH 的刷新周期:119

/* REFRESH parameter */

#define REFEN                   0x1     /* Refresh enable */

#define TREFMD                  0x0     /* CBR(CAS before RAS)/Auto refresh */

//#define Trp                      0x0     /* 2clk */

 

#define Trc                     0x3     /* 7clk */

#define Tchr                    0x2     /* 3clk */

//#define REFCNT                        0x0459

# if defined(CONFIG_S3C2440)

#define Trp            0x2    /* 4clk */

#define REFCNT            1012

#else

#define Trp            0x0    /* 2clk */

#define REFCNT                  0x0459

#endif

 

 

3.4 board/mini2440/mini2440.c 中对GPIOPLL的配置进行修改

(1)添加网络头文件的支持34

#include

#include 3c24x0_cpu.h>

 

#include

#include

2)修改GPIOPLL的配置

#if FCLK_SPEED==0               /* Fout = 203MHz, Fin = 12MHz for Audio */

#define M_MDIV  0xC3

#define M_PDIV  0x4

#define M_SDIV  0x1

#elif FCLK_SPEED==1             /* Fout = 202.8MHz */

//#define M_MDIV        0x5c

//define M_PDIV     0x4

//#define M_SDIV        0x0

 

#if defined(CONFIG_S3C2410)

/* Fout = 202.8MHz */

#define M_MDIV  0xA1

#define M_PDIV   0x3

#define M_SDIV   0x1

#endif

 

#if defined(CONFIG_S3C2440)

/* Fout = 405MHz */

#define M_MDIV  0x7f

#define M_PDIV  0x2

#define M_SDIV  0x1

#endif

#endif

 

#if USB_CLOCK==0

#define U_M_MDIV        0xA1

#define U_M_PDIV        0x3

#define U_M_SDIV        0x1

#elif USB_CLOCK==1

 

#if defined(CONFIG_S3C2410)

#define U_M_MDIV     0x48

#define U_M_PDIV      0x3

#endif

 

#if defined(CONFIG_S3C2440)

#define U_M_MDIV 0x38

#define U_M_PDIV 0x2

#endif

#define U_M_SDIV        0x2

#endif

3)为连接LED和蜂鸣器的GPIO修改配置寄存器:

        /* set up the I/O ports */

        gpio->GPACON = 0x007FFFFF;

//gpio->GPBCON = 0x00044556;

#if defined(CONFIG_MINI2440)

        gpio->GPBCON = 0x00055555;

#else

        gpio->GPBCON = 0x00044556;

#endif

        gpio->GPBUP = 0x000007FF;

。。。。。。

4)为引导linux 内核,修改开发板的类型代码

 

#if defined(CONFIG_S3C2410)

  /* arch number of SMDK2410-Board */

  gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;

#endif

 

#if defined(CONFIG_S3C2440)

/* arch number ofMINI2440-Board */

        gd->bd->bi_arch_number = MACH_TYPE_MINI2440 ;

#endif

5)为使int board_init (void)设置完成后,LED1LED2同时亮起,在int board_init (void)的最后添加:

    /* adress of boot parameters */

gd->bd->bi_boot_params = 0x30000100  

             icache_enable();

        dcache_enable();

# if defined(CONFIG_MINI2440_LED)

    gpio->GPBDAT = 0x181;

#endif

return 0;
}

 

(6)删除自带的nandflash的初始化函数

 

#if 0

#if defined(CONFIG_CMD_NAND)

extern ulong nand_probe(ulong physadr);

 

static inline void NF_Reset(void)

{

int i;

………………

#ifdef DEBUG

printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);

#endif

printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);

}

#endif

#endif

(7) 添加对dm9000的初始化函数

#ifdef CONFIG_CMD_NET

int board_eth_init(bd_t *bis)

{

  int rc = 0;

#ifdef CONFIG_CS8900

  rc = cs8900_initialize(0, CONFIG_CS8900_BASE);

#endif

#ifdef CONFIG_DRIVER_DM9000

  rc = dm9000_initialize(bis);

#endif

  return rc;

}

#endif

 

3.5修改 lib_arm/board.c文件

(1) 添加头文件支持52

#include

#include

#include

#include 3c24x0_cpu.h>  

#include  

 (2)删除不需要的指示进度LED功能,

 

#if 0

/***************************************************************

 * Coloured LED functionality

 ********************************************************************

May be supplied by boards if desired

 */

void inline __coloured_LED_init (void) {}

……………………

void inline blue_LED_off(void)__attribute__((weak, alias("__blue_LED_off")));

#endif

 

138

static int display_banner (void) 

{

#if defined(CONFIG_MINI2440_LED)  

struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();

gpio->GPBDAT = 0x101;

#endif

………

if defined(CONFIG_RESET_PHY_R)

debug ("Reset Ethernet PHY\n");

reset_phy();

#endif

#endif

 

446行》

 

#if defined(CONFIG_MINI2440_LED)  

struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();

         gpio->GPBDAT = 0x0;/* close*/

#endif

       printf("\n******************************************************");

 printf("\nhello! this U-BOOT is modified  by  XUJUN, at 2010-06-1\n ");

 printf("\t-USTB--xujun--beijing--mini2440-uboot-\n");

printf("\t  QQ is 306141829\n");

 printf("\t-LOVE ARM Linux and U-BOOT-\n");

printf("*******************************************************\n");

 

/* main_loop() can return to retry autoboot, if so just run it again. */

for (;;) {

    main_loop ();

}

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