当前位置: 首页 > 嵌入式Linux > 正文

Linux移植随笔:让内核支持nor flash

内核:linux-2.6.37.3

nor flash芯片:SST39VF6401B

网上有文章说了如何让linux内核支持nor flash。不过那些转载的文章中没有头文件(因为使用了<尖括号>,在一些网页中是不会显示的,详细请参考HTML相关资料)。后来研究了类似的驱动文件,发现它们都是大同小异,只是在一些参数上有改变而已。本文中源代码基于那些转载文章的代码。

MTD设备驱动程序在./driver/mtd下面,分为nor flash和nand flash两种。在chips中定义了几种访问nor的接口,包括cfi、jedec、map_ram和map_rom,而实际芯片所要添加的“驱动程序”放到maps目录下(比如本文使用的s3c2440-flash.c文件,详见文章后面)。从map这个单词来看,它描述的是一些映射信息,当然也包括了芯片信息,如总大小、块总数、访问接口等等。

这个过程其实是在内核代码树中添加自己的驱动的过程,当然是一些“标准”步骤了:在对应的代码树目录下,添加驱动源代码文件、在Makefile添加内容、在Kconfig添加内容,当然,还需要在make menuconfig里配置。

1、./driver/mtd/maps/Makefile

在这个Makefile最后添加:

obj-$(CONFIG_MTD_S3C2440) += s3c2440-flash.o

这个CONFIG_MTD_S3C2440由内核配置所得。

 

2、./driver/mtd/maps/Kconfig

在这个Kconfig文件最后添加(但在endmenu之前):

config MTD_S3C2440

tristate “CFI Flash device mapped on S3C2440″

depends on ARM && MTD_CFI

help

This enables access to the CFI Flash on the SMDK2440 board.

If you have such a board, say ‘Y’ here.

这里的MTD_S3C2440就是前面Makefile中的那个,注意,CONFIG_前缀是内核自己添加的。可以在编译内核后生成的autoconf.h文件中查看该宏定义。

3、内核配置

在Device Drivers  —>   <*> Memory Technology Device (MTD) support  —> 下面:

Mapping drivers for chip access  —>

<*> CFI Flash device mapped on S3C2440

RAM/ROM/Flash chip drivers —>

<*> Detect flash chips by Common Flash Interface (CFI) probe

[*] Flash chip driver advanced configuration options

[*]   Specific CFI Flash geometry selection

[*]     Support 16-bit buswidth

[*]     Support 1-chip flash interleave

4、./driver/mtd/maps/s3c2440-flash.c

代码见文章后面。

这个文件主要是修改前面的几个宏定义。我特地添加一些调试语句。开始时我使用2.6.30.2内核,驱动中使用cfi_probe接口,但是没有显示分区信息,后来我添加多几个接口才发现它是使用map_rom。这个过程花费了一些时间。

在2.6.30.2内核中,启动信息如下:

S3C2440-NOR:0x00800000 at 0x01000000

S3C2440-NOR:func:init_s3c2440nor[120] mymtd:0 type:cfi_probe

S3C2440-NOR:func:init_s3c2440nor[120] mymtd:0 type:jedec_probe

S3C2440-NOR:func:init_s3c2440nor[120] mymtd:c39cb600 type:map_rom

S3C2440-NOR:using static partition definition

Creating 4 MTD partitions on “NOR Flash(SST39VF6401B) on S3C2440″:

0x000000000000-0x000000030000 : “U-Boot”

0x000000030000-0x000000240000 : “Kernel”

0x000000240000-0x0000007f0000 : “RootFS(jffs2)”

0x0000007f0000-0x000000800000 : “Parameter”

可以看到,的确是使用map_rom接口。但是,当我使用2.6.37.2时,发现它使用的是cfi_probe接口,启动信息如下:

S3C2440-NOR:0x00800000 at 0x01000000

NOR Flash(SST39VF6401B) on S3C2440: Found 1 x16 devices at 0x0 in 16-bit bank.

Manufacturer ID 0x0000bf Chip ID 0x00236d

number of CFI chips: 1

## LL debug S3C2440-NOR:func:init_s3c2440nor[121] mymtd:c3a19200 type:cfi_probe

mtd: Giving out device 0 to NOR Flash(SST39VF6401B) on S3C2440

S3C2440-NOR:using static partition definition

Creating 4 MTD partitions on “NOR Flash(SST39VF6401B) on S3C2440″:

0x000000000000-0x000000030000 : “U-Boot”

mtd: Giving out device 1 to U-Boot

0x000000030000-0x000000240000 : “Kernel”

mtd: Giving out device 2 to Kernel

0x000000240000-0x0000007f0000 : “Rootfs(jffs2)”

mtd: Giving out device 3 to Rootfs(jffs2)

0x0000007f0000-0x000000800000 : “Parameter”

mtd: Giving out device 4 to Parameter

与前面不同的是,它打印了芯片的信息,如厂商ID、芯片ID等等。

这是我想不通的地方,也是我采用新内核的原因。

不过,在这片nor flash上使用jffs2文件系统却不成功,出现了大量的警告信息,提示说制作根文件系统时的erase block有问题。

s3c2440-flash.c源代码:

/*

* $Id: s3c2410.c,v 1.00 2006/12/05 10:18:14 gleixner Exp $

*

* Handle mapping of the NOR flash on Cogent S3C2410 boards

*

* Copyright 2002 SYSGO Real-Time Solutions GmbH

*

* This program is free software; you can redistribute it and/or modify

* it under the terms of the GNU General Public License version 2 as

* published by the Free Software Foundation.

*/

/*

*                 Late Lee

* This file is modified and the file name has changed to ‘s3c2440-flash.c’.

* The SMDK2440 board has only one flash bank which is a 64Mbit(4Mx16) SST SST39VF6401B;

* 128 x 64 KiB blocks.

*

* This code is GPLed.

*/

#include <linux/module.h>

#include <linux/types.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <asm/io.h>

#include <linux/mtd/mtd.h>

#include <linux/mtd/map.h>

#include <linux/mtd/cfi.h>

#ifdef CONFIG_MTD_PARTITIONS

#include <linux/mtd/partitions.h>

#endif

#define WINDOW_ADDR 0x01000000       /* physical properties of flash */

#define WINDOW_SIZE 0x800000 /* 8MB */

#define BUSWIDTH    2 /* 2*8 = 16 */

#define FLASH_BLOCKSIZE_MAIN        0x10000  /* 64KB(0x10000) 128 blocks */

#define FLASH_NUMBLOCKS_MAIN        128

/* can be “cfi_probe”, “jedec_probe”, “map_rom”, NULL }; */

#define PROBETYPES { “cfi_probe”“jedec_probe”“map_rom”, NULL }

#define MSG_PREFIX “S3C2440-NOR:”    /* prefix for our printk()’s */

#define MTDID      “s3c2440-nor”     /* for mtdparts= partitioning */

#define DEBUG_FLASH

#ifdef DEBUG_FLASH

#define flash_debug(fmt, args…) printk(KERN_NOTICE “## LL debug “ MSG_PREFIX  fmt, ##args)

#else

#define flash_debug(fmt, args…)

#endif

static struct mtd_info *mymtd;

struct map_info s3c2440nor_map = {

.name = “NOR Flash(SST39VF6401B) on S3C2440″,

.size = WINDOW_SIZE,

.bankwidth = BUSWIDTH,

.phys = WINDOW_ADDR,

};

#ifdef CONFIG_MTD_PARTITIONS

/*

* MTD partitioning stuff

*/

static struct mtd_partition static_partitions[] = {

/*0: U-Boot: 0-0x30000 0x30000=192KB*/

{

.name = “U-Boot”,

.size = 0x030000,

.offset = 0x0,

},

/*1: Kernel: 0x30000-0x240000 0x210000=2112KB=2.0625MB*/

{

.name = “Kernel”,

.size = 0x210000,

.offset = 0x30000,

},

/*2: Rootfs(jffs2): 0x240000-0x7f0000 0x5b0000=5824KB=5.6875MB*/

{

.name = “Rootfs(jffs2)”,

.size = 0x5b0000,

.offset = 0x240000,

},

/*3: U-Boot Parameters: 0x7f0000-0x800000 0x10000=64KB*/

{.name = “Parameter”,

.size = 0x010000,

.offset = 0x7f0000,

},

};

//static const char *probes[] = { “RedBoot”, “cmdlinepart”, NULL };

static const char *probes[] = { NULL };

#endif

static int mtd_parts_nb = 0;

static struct mtd_partition *mtd_parts = 0;

int __init init_s3c2440nor(void)

{

static const char *rom_probe_types[] = PROBETYPES;

const char **type;

const char *part_type = 0;

printk(KERN_NOTICE MSG_PREFIX “0x%08x at 0x%08xn”,

WINDOW_SIZE, WINDOW_ADDR);

s3c2440nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);

if (!s3c2440nor_map.virt) {

printk(MSG_PREFIX “failed to ioremapn”);

                   return -EIO;

}

simple_map_init(&s3c2440nor_map);

mymtd = 0;

type = rom_probe_types;

for(; !mymtd && *type; type++) {

mymtd = do_map_probe(*type, &s3c2440nor_map);

flash_debug(“func:%s[%d] mymtd:%x type:%sn”, __func__, __LINE__, mymtd, *type);

}

if (mymtd) {

mymtd->owner = THIS_MODULE;

                   #ifdef CONFIG_MTD_PARTITIONS

mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);

                   if (mtd_parts_nb > 0)

part_type = “detected”;

                   if (mtd_parts_nb == 0){

mtd_parts = static_partitions;

mtd_parts_nb = ARRAY_SIZE(static_partitions);

part_type = “static”;

}

                   #endif

add_mtd_device(mymtd);

                   if (mtd_parts_nb == 0)

printk(KERN_NOTICE MSG_PREFIX “no partition info availablen”);

                   else{

printk(KERN_NOTICE MSG_PREFIX

                              “using %s partition definitionn”, part_type);

add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb);

}

                   return 0;

}

iounmap((void *)s3c2440nor_map.virt);

return -ENXIO;

}

static void __exit cleanup_s3c2440nor(void)

{

if (mymtd) {

del_mtd_device(mymtd);

map_destroy(mymtd);

}

if (s3c2440nor_map.virt) {

iounmap((void *)s3c2440nor_map.virt);

s3c2440nor_map.virt = 0;

}

}

module_init(init_s3c2440nor);

module_exit(cleanup_s3c2440nor);

MODULE_LICENSE(“GPL”);

MODULE_AUTHOR(“GengYaoJun “);

MODULE_DESCRIPTION(“Generic configurable MTD map driver”);

本文固定链接: http://www.latelee.org/embedded-linux/nor-flash-to-kernel.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: Linux移植随笔:让内核支持nor flash | 迟思堂工作室

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter