前言:这是本人在学习u-boot期间的初级移植笔记,故功能较简陋、代码较粗略,后续会有高级篇完善。u-boot版本:1.1.6交叉编译器:3.4.5开发板:友善之臂mini2440开发板配置:SoC s3c2440 、网卡 DM9000 、 Nor Flash AM29LV160DB (2M) 、NAND FLash (256M) 、SDRAM (64M)以源文件已存在的 smdk2410项目为基础进行移植工作1.移植准备工作
1).下载u-boot-1.1.6源码,并解压;2).建立u-boot的source insight工程,方便查找及分析;3).安装arm-Linux交叉编译器,版本3.4.5;
2.修改顶层Makefile
1).打开 /Makefile ,找到smdk2410板配置选项:
- smdk2410_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
smdk2410_config:unconfig@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0各项参数意义: arm:CPU架构 arm920t:CPU型号 smdk2410:开发板名称 NULL:开发者 s3c24x0:片上系统类比此项添加配置选项:
- mini2440_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
mini2440_config:unconfig@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
3.建立主代码
1).找到 /board/smdk2410 目录,将此目录复制为 /board/mini2440 ,打开mini2440目录,将smdk2410.c文件重命名为mini2440.c。打开同目录下Makefile文件,修改代码
- COBJS := smdk2410.o flash.o
COBJS:= smdk2410.o flash.o为
- COBJS := mini2440.o flash.o
COBJS:= mini2440.o flash.o2).建立开发板配置头文件。将 /include/configs/smdk2410.h 复制为 /include/configs/mini2440.h ,打开此文件,添加
- #define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
#defineCONFIG_S3C24401/* in a SAMSUNG S3C2440 SoC */
4.修改CPU频率设置
1).将以上步骤建立的代码编译测试:
- root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make mini2440_config
- Configuring for mini2440 board...
- root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make
root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make mini2440_configConfiguring for mini2440 board...root@book-desktop:/home/book/Desktop/u-boot-1.1.6# make生成u-boot.bin 下载至开发板运行,发现并未打印出任何信息。原因是2410和2440在频率设置方面有所不同。2). 打开 /board/mini2440/mini2440.c ,屏蔽下列代码
- #if 0
- #define FCLK_SPEED 1
-
- #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 0xA1
- #define M_PDIV 0x3
- #define M_SDIV 0x1
- #endif
-
- #define USB_CLOCK 1
-
- #if USB_CLOCK==0
- #define U_M_MDIV 0xA1
- #define U_M_PDIV 0x3
- #define U_M_SDIV 0x1
- #elif USB_CLOCK==1
- #define U_M_MDIV 0x48
- #define U_M_PDIV 0x3
- #define U_M_SDIV 0x2
- #endif
- #endif
#if 0#define FCLK_SPEED 1#if FCLK_SPEED==0/* Fout = 203MHz, Fin = 12MHz for Audio */#define M_MDIV0xC3#define M_PDIV0x4#define M_SDIV0x1#elif FCLK_SPEED==1/* Fout = 202.8MHz */#define M_MDIV0xA1#define M_PDIV0x3#define M_SDIV0x1#endif#define USB_CLOCK 1#if USB_CLOCK==0#define U_M_MDIV0xA1#define U_M_PDIV0x3#define U_M_SDIV0x1#elif USB_CLOCK==1#define U_M_MDIV0x48#define U_M_PDIV0x3#define U_M_SDIV0x2#endif#endif然后修改board_init函数
- int board_init (void)
- {
- S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
- S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
-
- clk_power->CLKDIVN = 0x05; /* 1 : 4 : 8 */
-
- __asm__( "mrc p15,0,r1,c1,c0,0
"
- "orr r1,r1,#0xc0000000
"
- "mcr p15,0,r1,c1,c0,0
"
- :::"r1"
- );//异步总线
-
- /* to reduce PLL lock time, adjust the LOCKTIME register */
- clk_power->LOCKTIME = 0xFFFFFF;
-
- /* configure MPLL */
- clk_power->MPLLCON = ((0x5c << 12) + (0x01 << 4) + 0x01); //400MHz
-
- /* some delay between MPLL and UPLL */
- delay (4000);
-
- /* configure UPLL */
- clk_power->UPLLCON = ((0x38 << 12) + (0x02 << 4) + 0x02); //48MHz
-
- /* some delay between MPLL and UPLL */
- delay (8000);
-
- /* set up the I/O ports */
- gpio->GPACON = 0x007FFFFF;
- gpio->GPBCON = 0x00044555;
- gpio->GPBUP = 0x000007FF;
- gpio->GPCCON = 0xAAAAAAAA;
- gpio->GPCUP = 0x0000FFFF;
- gpio->GPDCON = 0xAAAAAAAA;
- gpio->GPDUP = 0x0000FFFF;
- gpio->GPECON = 0xAAAAAAAA;
- gpio->GPEUP = 0x0000FFFF;
- gpio->GPFCON = 0x000055AA;
- gpio->GPFUP = 0x000000FF;
- gpio->GPGCON = 0xFF95FFBA;
- gpio->GPGUP = 0x0000FFFF;
- gpio->GPHCON = 0x002AFAAA;
- gpio->GPHUP = 0x000007FF;
-
- /* arch number of SMDK2410-Board */
- gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
-
- /* adress of boot parameters */
- gd->bd->bi_boot_params = 0x30000100;
-
- icache_enable();
- dcache_enable();
-
- return 0;
- }
int board_init (void){S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();clk_power->CLKDIVN = 0x05; /* 1 : 4 : 8 */__asm__("mrc p15,0,r1,c1,c0,0
""orr r1,r1,#0xc0000000
""mcr p15,0,r1,c1,c0,0
":::"r1");//异步总线/* to reduce PLL lock time, adjust the LOCKTIME register */clk_power->LOCKTIME = 0xFFFFFF;/* configure MPLL */clk_power->MPLLCON = ((0x5c << 12) + (0x01 << 4) + 0x01); //400MHz/* some delay between MPLL and UPLL */delay (4000);/* configure UPLL */clk_power->UPLLCON = ((0x38 << 12) + (0x02 << 4) + 0x02); //48MHz/* some delay between MPLL and UPLL */delay (8000);/* set up the I/O ports */gpio->GPACON = 0x007FFFFF;gpio->GPBCON = 0x00044555;gpio->GPBUP = 0x000007FF;gpio->GPCCON = 0xAAAAAAAA;gpio->GPCUP = 0x0000FFFF;gpio->GPDCON = 0xAAAAAAAA;gpio->GPDUP = 0x0000FFFF;gpio->GPECON = 0xAAAAAAAA;gpio->GPEUP = 0x0000FFFF;gpio->GPFCON = 0x000055AA;gpio->GPFUP = 0x000000FF;gpio->GPGCON = 0xFF95FFBA;gpio->GPGUP = 0x0000FFFF;gpio->GPHCON = 0x002AFAAA;gpio->GPHUP = 0x000007FF;/* arch number of SMDK2410-Board */gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;/* adress of boot parameters */gd->bd->bi_boot_params = 0x30000100;icache_enable();dcache_enable();return 0;}3).串口初始化时需要获取系统时钟,这里修改 /cpu/arm920t/s3c24x0/speed.c ,get_PLLCLK()中
- return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
return((CONFIG_SYS_CLK_FREQ * m) / (p << s));改为
- return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));这是因为2410和2440主频计算公式的差异。
其他修改:
- /* return HCLK frequency */
- ulong get_HCLK(void)
- {
- return(get_FCLK()/4 );
- }
-
- /* return PCLK frequency */
- ulong get_PCLK(void)
- {
- return(get_HCLK()/2 );
- }
/* return HCLK frequency */ulong get_HCLK(void){return(get_FCLK()/4 );}/* return PCLK frequency */ulong get_PCLK(void){return(get_HCLK()/2 );}再次进行编译测试,出现打印信息:
- U-Boot 1.1.6 (Jan 26 2017 - 17:10:05)
-
- DRAM: 64 MB
- Flash: 512 kB
- *** Warning - bad CRC, using default environment
-
- In: serial
- Out: serial
- Err: serial
- SMDK2410 #
5.支持Nor Flash AM29lv160DB
打开 mini2440.h 头文件,发现flash配置项只有CONFIG_AMD_LV400和CONFIG_AMD_LV800,没有本型号,因为AM29lv160DB符合CFI接口标准,故使用 /drivers/cfi_flash.c 中的接口函数。进行下列修改:1).屏蔽代码
- /*-----------------------------------------------------------------------
- * FLASH and environment organization
- */
- #if 0
- #define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
- #define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
- #endif
/*----------------------------------------------------------------------- * FLASH and environment organization */#if 0#define CONFIG_AMD_LV4001/* uncomment this if you have a LV400 flash */#define CONFIG_AMD_LV8001/* uncomment this if you have a LV800 flash */#endif增加宏定义
- #define CFG_FLASH_CFI_DRIVER 1
修改代码
- #define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
- #ifdef CONFIG_AMD_LV800
- #define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
- #define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
- #define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
- #endif
- #ifdef CONFIG_AMD_LV400
- #define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
- #define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
- #define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
- #endif
为
- #define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
- #ifdef CONFIG_AMD_LV800
- #define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
- #define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
- #define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
- #elif defined CONFIG_AMD_LV400
- #define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
- #define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
- #define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
- #else
- #define PHYS_FLASH_SIZE 0x00200000 /* 2MB */
- #define CFG_MAX_FLASH_SECT (99) /* max number of sectors on one chip */
- #define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x1F0000) /* addr of environment */
- #endif
#define CFG_MAX_FLASH_BANKS1/* max number of memory banks */#ifdef CONFIG_AMD_LV800#define PHYS_FLASH_SIZE0x00100000 /* 1MB */#define CFG_MAX_FLASH_SECT(19)/* max number of sectors on one chip */#define CFG_ENV_ADDR(CFG_FLASH_BASE + 0x0F0000) /* addr of environment */#elif defined CONFIG_AMD_LV400#define PHYS_FLASH_SIZE0x00080000 /* 512KB */#define CFG_MAX_FLASH_SECT(11)/* max number of sectors on one chip */#define CFG_ENV_ADDR(CFG_FLASH_BASE + 0x070000) /* addr of environment */#else#define PHYS_FLASH_SIZE0x00200000 /* 2MB */#define CFG_MAX_FLASH_SECT(99)/* max number of sectors on one chip */#define CFG_ENV_ADDR(CFG_FLASH_BASE + 0x1F0000) /* addr of environment */#endif2) 在 /board/mini2440/makefile 中COBJS := mini2440.o flash.o去掉flash.o ,再次编译测试,出现错误:
- cfi_flash.c:411: error: `CFG_MONITOR_BASE" undeclared (first use in this function)
在mini2440.h中加入宏定义
- #define CFG_MONITOR_BASE 0
- #define CFG_FLASH_CFI 1
再次编译,通过!烧写至开发板,打印出信息:
- Flash: 2 MB
Flash:2 MB输入命令 flinfo得到信息:
- SMDK2410 # flinfo
-
- Bank # 1: CFI conformant FLASH (16 x 16) Size: 2 MB in 35 Sectors
- Erase timeout 8192 ms, write timeout 1 ms, buffer write timeout 1 ms, buffer size 1
- Sector Start Addresses:
- 00000000 (RO) 00004000 (RO) 00006000 (RO) 00008000 (RO) 00010000 (RO)
- 00020000 00030000 00040000 00050000 00060000
- 00070000 00080000 00090000 000A0000 000B0000
- 000C0000 000D0000 000E0000 000F0000 00100000
- 00110000 00120000 00130000 00140000 00150000
- 00160000 00170000 00180000 00190000 001A0000
- 001B0000 001C0000 001D0000 001E0000 001F0000 (RO)
- SMDK2410 #
至此nor flash支持移植成功。
6.支持DM9000网卡
smdk2410支持cs8900网卡,本开发板使用DM9000网卡,/drivers/dm9000x.c 是对应的网卡驱动。1) 在mini2440.h中,将以下关于cs8900的宏注释掉,并添加DM9000宏定义:
- /*
- * Hardware drivers
- */
- #if 0
- #define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
- #define CS8900_BASE 0x19000300
- #define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
- #endif
- #define CONFIG_DRIVER_DM9000 1
编译,出现错误提示:
- dm9000x.c:374: error: `DM9000_IO" undeclared (first use in this function)
- dm9000x.c:445: error: `DM9000_DATA" undeclared (first use in this function)
- dm9000x.c:144: error: `CONFIG_DM9000_BASE" undeclared
以此继续增加宏定义:
- #define CONFIG_DM9000_BASE 0x20000000
- #define DM9000_IO 0x20000000
- #define DM9000_DATA (DM9000_IO + 0x4)
- #define CONFIG_DM9000_USE_16BIT 1
查看原理图可得本开发板网卡片选线接在BANK4,故基地址为0x20000000,IO为基地址,DATA与基地址偏移0x04,此外定义16BIT表示网卡使用16BIT模式。2) 修改默认网络参数,mini2440.h 中修改代码:
- #define CONFIG_NETMASK 255.255.255.0
- #define CONFIG_IPADDR 192.168.31.111
- #define CONFIG_SERVERIP 192.168.31.245
#define CONFIG_NETMASK255.255.255.0#define CONFIG_IPADDR192.168.31.111#define CONFIG_SERVERIP192.168.31.245还有取消屏蔽:
- #define CONFIG_ETHADDR 08:00:3e:26:0a:5b
再次编译,通过!下载至开发板,运行测试ping和tftp命令:发现ping无效,tftp可用。原因是未添加PING命令宏定义,故在mini2440.h中添加相关宏:
- #define CONFIG_COMMANDS
- (CONFIG_CMD_DFL |
- CFG_CMD_CACHE |
- /*CFG_CMD_NAND |*/
- /*CFG_CMD_EEPROM |*/
- /*CFG_CMD_I2C |*/
- /*CFG_CMD_USB |*/
- CFG_CMD_REGINFO |
- CFG_CMD_DATE |
- CFG_CMD_PING |
再次测试,得到打印结果:
- SMDK2410 # ping 192.168.31.245
- dm9000 。。。。。
- host 192.168.31.245 is alive
SMDK2410 # ping 192.168.31.245dm9000 。。。。。host 192.168.31.245 is alive至此,dm9000支持移植成功。
7.支持NAND FLASH
nand的驱动代码在 /drivers/nand 目录下面,打开此目录下的nand.c文件,看到如下代码
- #include <common.h>
-
- #if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
-
- #include <nand.h>
所以判断使用nand驱动的宏开关为CFG_CMD_NAND。1) 在mini2440.h中的CONFIG_COMMANDS中加入宏定义 CFG_CMD_NAND
- #define CONFIG_COMMANDS
- (CONFIG_CMD_DFL |
- CFG_CMD_CACHE |
- CFG_CMD_NAND |
- /*CFG_CMD_EEPROM |*/
- /*CFG_CMD_I2C |*/
然后启动编译,错误如下:
- nand.c:35: error: `CFG_MAX_NAND_DEVICE" undeclared here (not in a function)
- nand.c:38: error: `CFG_NAND_BASE" undeclared here (not in a function)
- home/book/Desktop/u-boot-1.1.6/include/linux/mtd/nand.h:412: error: `NAND_MAX_CHIPS" undeclared here (not in a function)
home/book/Desktop/u-boot-1.1.6/include/linux/mtd/nand.h:412: error: `NAND_MAX_CHIPS" undeclared here (not in a function)在mini2440.h中添加以上宏定义:
- /*NAND FLASH*/
- #define CFG_MAX_NAND_DEVICE 1
- #define CFG_NAND_BASE 0x0
- #define NAND_MAX_CHIPS 1
/*NAND FLASH*/#define CFG_MAX_NAND_DEVICE1#define CFG_NAND_BASE0x0#define NAND_MAX_CHIPS1三者分别表示: nand设备数量; nand基地址,无实际意义,在board_nand_init函数中会被重新指定; 每个nand设备有1个nand芯片;再次编译,出现错误为:
- drivers/nand/libnand.a(nand.o)(.text+0x24): In function `nand_init":
- /home/book/Desktop/u-boot-1.1.6/drivers/nand/nand.c:50: undefined reference to `board_nand_init"
意思是board_nand_init函数未定义。上电后nand的初始化过程为:start_armboot函数调用nand_init,nand_init函数在 /drivers/nand/nand.c中实现,nand_init函数调用同文件中nand_init_chip函数,nand_init_chip函数会首先调用board_nand_init函数来初始化nand设备。此函数是硬件相关,需要自己写。下一步实现此函数。2) 实现board_nand_init函数。在 /cpu/arm920t/s3c24x0/ 目录下建立文件nand_flash.c,文件内容为:
- /*
- * Nand flash interface of s3c2410/s3c2440
- */
-
- #include <common.h>
-
- #if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
- #include <s3c2410.h>
- #include <nand.h>
-
- DECLARE_GLOBAL_DATA_PTR;
-
- #define S3C2410_NFSTAT_READY (1<<0)
- #define S3C2410_NFCONF_nFCE (1<<11)
-
- #define S3C2440_NFSTAT_READY (1<<0)
- #define S3C2440_NFCONT_nFCE (1<<1)
-
-
- /* select chip, for s3c2410 */
- static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
- {
- S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
-
- if (chip == -1) {
- s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
- } else {
- s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
- }
- }
-
- /* command and control functions, for s3c2410
- *
- * Note, these all use tglx"s method of changing the IO_ADDR_W field
- * to make the code simpler, and use the nand layer"s code to issue the
- * command and address sequences via the proper IO ports.
- *
- */
- static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
- {
- S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
- struct nand_chip *chip = mtd->priv;
-
- switch (cmd) {
- case NAND_CTL_SETNCE:
- case NAND_CTL_CLRNCE:
- printf("%s: called for NCE
", __FUNCTION__);
- break;
-
- case NAND_CTL_SETCLE:
- chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
- break;
-
- case NAND_CTL_SETALE:
- chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
- break;
-
- /* NAND_CTL_CLRCLE: */
- /* NAND_CTL_CLRALE: */
- default:
- chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
- break;
- }
- }
-
- /* s3c2410_nand_devready()
- *
- * returns 0 if the nand is busy, 1 if it is ready
- */
- static int s3c2410_nand_devready(struct mtd_info *mtd)
- {
- S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
-
- return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
- }
-
-
- /* select chip, for s3c2440 */
- static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
- {
- S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
-
- if (chip == -1) {
- s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
- } else {
- s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
- }
- }
-
- /* command and control functions */
- static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
- {
- S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
- struct nand_chip *chip = mtd->priv;
-
- switch (cmd) {
- case NAND_CTL_SETNCE:
- case NAND_CTL_CLRNCE:
- printf("%s: called for NCE
", __FUNCTION__);
- break;
-
- case NAND_CTL_SETCLE:
- chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
- break;
-
- case NAND_CTL_SETALE:
- chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
- break;
-
- /* NAND_CTL_CLRCLE: */
- /* NAND_CTL_CLRALE: */
- default:
- chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
- break;
- }
- }
-
- /* s3c2440_nand_devready()
- *
- * returns 0 if the nand is busy, 1 if it is ready
- */
- static int s3c2440_nand_devready(struct mtd_info *mtd)
- {
- S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
-
- return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
- }
-
- /*
- * Nand flash hardware initialization:
- * Set the timing, enable NAND flash controller
- */
- static void s3c24x0_nand_inithw(void)
- {
- S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
- S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
-
- #define TACLS 0
- #define TWRPH0 4
- #define TWRPH1 2
-
- if (0)
- {
- /* Enable NAND flash controller, Initialize ECC, enable chip select, Set flash memory timing */
- s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
- }
- else
- {
- /* Set flash memory timing */
- s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
- /* Initialize ECC, enable chip select, NAND flash controller enable */
- s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
- }
- }
-
- /*
- * Called by drivers/nand/nand.c, initialize the interface of nand flash
- */
- void board_nand_init(struct nand_chip *chip)
- {
- S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
- S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
-
- s3c24x0_nand_inithw();
-
- if (0) {
- chip->IO_ADDR_R = (void *)&s3c2410nand->NFDATA;
- chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
- chip->hwcontrol = s3c2410_nand_hwcontrol;
- chip->dev_ready = s3c2410_nand_devready;
- chip->select_chip = s3c2410_nand_select_chip;
- chip->options = 0;
- } else {
- chip->IO_ADDR_R = (void *)&s3c2440nand->NFDATA;
- chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
- chip->hwcontrol = s3c2440_nand_hwcontrol;
- chip->dev_ready = s3c2440_nand_devready;
- chip->select_chip = s3c2440_nand_select_chip;
- chip->options = 0;
- }
-
- chip->eccmode = NAND_ECC_SOFT;
- }
-
- #endif
/* * Nand flash interface of s3c2410/s3c2440 */#include <common.h>#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)#include <s3c2410.h>#include <nand.h>DECLARE_GLOBAL_DATA_PTR;#define S3C2410_NFSTAT_READY(1<<0)#define S3C2410_NFCONF_nFCE (1<<11)#define S3C2440_NFSTAT_READY(1<<0)#define S3C2440_NFCONT_nFCE (1<<1)/* select chip, for s3c2410 */static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip){S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();if (chip == -1) {s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;} else {s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;}}/* command and control functions, for s3c2410* * Note, these all use tglx"s method of changing the IO_ADDR_W field * to make the code simpler, and use the nand layer"s code to issue the * command and address sequences via the proper IO ports. **/static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd){S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();struct nand_chip *chip = mtd->priv;switch (cmd) {case NAND_CTL_SETNCE:case NAND_CTL_CLRNCE:printf("%s: called for NCE
", __FUNCTION__);break;case NAND_CTL_SETCLE:chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;break;case NAND_CTL_SETALE:chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;break;/* NAND_CTL_CLRCLE: *//* NAND_CTL_CLRALE: */default:chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;break;}}/* s3c2410_nand_devready() * * returns 0 if the nand is busy, 1 if it is ready */static int s3c2410_nand_devready(struct mtd_info *mtd){S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);}/* select chip, for s3c2440 */static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip){S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();if (chip == -1) {s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;} else {s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;}}/* command and control functions */static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd){S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();struct nand_chip *chip = mtd->priv;switch (cmd) {case NAND_CTL_SETNCE:case NAND_CTL_CLRNCE:printf("%s: called for NCE
", __FUNCTION__);break;case NAND_CTL_SETCLE:chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;break;case NAND_CTL_SETALE:chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;break;/* NAND_CTL_CLRCLE: *//* NAND_CTL_CLRALE: */default:chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;break;}}/* s3c2440_nand_devready() * * returns 0 if the nand is busy, 1 if it is ready */static int s3c2440_nand_devready(struct mtd_info *mtd){S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);}/* * Nand flash hardware initialization: * Set the timing, enable NAND flash controller */static void s3c24x0_nand_inithw(void){S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();#define TACLS 0#define TWRPH04#define TWRPH12if (0){/* Enable NAND flash controller, Initialize ECC, enable chip select, Set flash memory timing */s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);}else{/* Set flash memory timing */s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);/* Initialize ECC, enable chip select, NAND flash controller enable */s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);}}/* * Called by drivers/nand/nand.c, initialize the interface of nand flash */void board_nand_init(struct nand_chip *chip){S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();s3c24x0_nand_inithw();if (0) {chip->IO_ADDR_R= (void *)&s3c2410nand->NFDATA;chip->IO_ADDR_W= (void *)&s3c2410nand->NFDATA;chip->hwcontrol= s3c2410_nand_hwcontrol;chip->dev_ready= s3c2410_nand_devready;chip->select_chip= s3c2410_nand_select_chip;chip->options= 0;} else {chip->IO_ADDR_R= (void *)&s3c2440nand->NFDATA;chip->IO_ADDR_W= (void *)&s3c2440nand->NFDATA;chip->hwcontrol= s3c2440_nand_hwcontrol;chip->dev_ready= s3c2440_nand_devready;chip->select_chip= s3c2440_nand_select_chip;chip->options= 0;}chip->eccmode = NAND_ECC_SOFT;}#endif还要在 /include/s3c24x0.h文件中增加本文件中使用到的S3C2440_NAND数据结构,在s3c2410_nand的下面,
- /* NAND FLASH (see S3C2410 manual chapter 6) */
- typedef struct {
- S3C24X0_REG32 NFCONF;
- S3C24X0_REG32 NFCMD;
- S3C24X0_REG32 NFADDR;
- S3C24X0_REG32 NFDATA;
- S3C24X0_REG32 NFSTAT;
- S3C24X0_REG32 NFECC;
- } /*__attribute__((__packed__))*/ S3C2410_NAND;
/* NAND FLASH (see S3C2410 manual chapter 6) */typedef struct {S3C24X0_REG32NFCONF;S3C24X0_REG32NFCMD;S3C24X0_REG32NFADDR;S3C24X0_REG32NFDATA;S3C24X0_REG32NFSTAT;S3C24X0_REG32NFECC;} /*__attribute__((__packed__))*/ S3C2410_NAND;增添2440nand的结构体:
- typedef struct {
- S3C24X0_REG32 NFCONF;
- S3C24X0_REG32 NFCONT;
- S3C24X0_REG32 NFCMD;
- S3C24X0_REG32 NFADDR;
- S3C24X0_REG32 NFDATA;
- S3C24X0_REG32 NFMECCD0;
- S3C24X0_REG32 NFMECCD1;
- S3C24X0_REG32 NFSECCD;
- S3C24X0_REG32 NFSTAT;
- S3C24X0_REG32 NFESTAT0;
- S3C24X0_REG32 NFESTAT1;
- S3C24X0_REG32 NFMECC0;
- S3C24X0_REG32 NFMECC1;
- S3C24X0_REG32 NFSECC;
- S3C24X0_REG32 NFSBLK;
- S3C24X0_REG32 NFEBLK;
- } /*__attribute__((__packed__))*/ S3C2440_NAND;
typedef struct {S3C24X0_REG32 NFCONF;S3C24X0_REG32 NFCONT;S3C24X0_REG32 NFCMD;S3C24X0_REG32 NFADDR;S3C24X0_REG32 NFDATA;S3C24X0_REG32 NFMECCD0;S3C24X0_REG32 NFMECCD1;S3C24X0_REG32 NFSECCD;S3C24X0_REG32 NFSTAT;S3C24X0_REG32 NFESTAT0;S3C24X0_REG32 NFESTAT1;S3C24X0_REG32 NFMECC0;S3C24X0_REG32 NFMECC1;S3C24X0_REG32 NFSECC;S3C24X0_REG32 NFSBLK;S3C24X0_REG32 NFEBLK;} /*__attribute__((__packed__))*/ S3C2440_NAND;然后打开同目录下的s3c2410.h,找到
- static inline S3C2410_NAND * const S3C2410_GetBase_NAND(void)
- {
- return (S3C2410_NAND * const)S3C2410_NAND_BASE;
- }
static inline S3C2410_NAND * const S3C2410_GetBase_NAND(void){return (S3C2410_NAND * const)S3C2410_NAND_BASE;}在其下面添加
- static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
- {
- return (S3C2440_NAND * const)S3C2410_NAND_BASE;
- }
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void){return (S3C2440_NAND * const)S3C2410_NAND_BASE;}最后将新建的nand_flash.c文件编入u-boot之中。打开 /cpu/arm920t/s3c24x0/Makefile ,在COBJS中增加nand_flash.o:
- COBJS = i2c.o interrupts.o serial.o speed.o
- usb_ohci.o nand_flash.o
COBJS= i2c.o interrupts.o serial.o speed.o usb_ohci.o nand_flash.o编译,通过!下载至开发板运行,控制台打印出:NAND : 256MiB,输入命令nand info,打印信息:
- NAND 256MiB 3.3V 8-bit, sector size 128 KiB
NAND 256MiB 3.3V 8-bit, sector size 128 KiB至此,NAND flash支持移植成功!
U-Boot源代码下载地址 http://www.linuxidc.com/Linux/2011-07/38897.htm
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-01/140034.htm