MTD NANDFLASH驱动相关知识介绍
轉:http://blog.csdn.net/zhouzhuan2008/article/details/11053877
?
目錄
- MTD總概述
- MTD數(shù)據(jù)結構?
- MTD相關層實現(xiàn)
字符設備和塊設備的區(qū)別在于前者只能被順序讀寫,后者可以隨機訪問;同時,兩者讀寫數(shù)據(jù)的基本單元不同。
字符設備,以字節(jié)為基本單位,在Linux中,字符設備實現(xiàn)的比較簡單,不需要緩沖區(qū)即可直接讀寫,內核例程和用戶態(tài)API一一對應,用戶層的Read函數(shù)直接對應了內核中的Read例程,這種映射關系由字符設備的file_operations維護。
塊設備,則以塊為單位接受輸入和返回輸出。對這種設備的讀寫是按塊進行的,其接口相對于字符設備復雜,read、write API沒有直接到塊設備層,而是直接到文件系統(tǒng)層,然后再由文件系統(tǒng)層發(fā)起讀寫請求。?
同時,由于塊設備的IO性能與CPU相比很差,因此,塊設備的數(shù)據(jù)流往往會引入文件系統(tǒng)的Cache機制。
MTD設備既非塊設備也不是字符設備,但可以同時提供字符設備和塊設備接口來操作它。
MTD總概述
Linux中MTD的所有源碼位于/drivers/mtd子目錄下,
MTD設備通常可分為四層?
這四層從上到下依次是:設備節(jié)點、MTD設備層、MTD原始設備層和硬件驅動層。
一、Flash硬件驅動層?
硬件驅動層負責在init時驅動Flash硬件并建立從具體設備到MTD原始設備映射關系?
tip: 映射關系通常包括 分區(qū)信息、I/O映射及特定函數(shù)的映射?
drivers/mtd/chips :?? CFI/jedec接口通用驅動?
drivers/mtd/nand :?? nand通用驅動和部分底層驅動程序?
drivers/mtd/maps :?? nor flash映射關系相關函數(shù)?
drivers/mtd/devices:?? nor flash底層驅動
二、MTD原始設備?
用于描述MTD原始設備的數(shù)據(jù)結構是mtd_info,它定義了大量的關于MTD的數(shù)據(jù)和操作函數(shù)。?
mtdcore.c :? MTD原始設備接口相關實現(xiàn)?
mtdpart.c :? MTD分區(qū)接口相關實現(xiàn)
三、MTD設備層?
基于MTD原始設備,linux系統(tǒng)可以定義出MTD的塊設備(主設備號31)和字符設備(設備號90)。?
mtdchar.c :? MTD字符設備接口相關實現(xiàn)?
mtdblock.c : MTD塊設備接口相關實現(xiàn)
四、設備節(jié)點?
通過mknod在/dev子目錄下建立MTD塊設備節(jié)點(主設備號為31)和MTD字符設備節(jié)點(主設備號為90)?
通過訪問此設備節(jié)點即可訪問MTD字符設備和塊設備?
具體參考:??working-with-mtd-devices
五、文件系統(tǒng)?
內核啟動后,通過mount 命令可以將flash中的其余分區(qū)作為文件系統(tǒng)掛載到mountpoint上。
MTD數(shù)據(jù)結構?
重要的數(shù)據(jù)結構:?
1. mtd_info 表示mtd原始設備, 所有mtd_info結構體被存放在mtd_info數(shù)組mtd_table中
2. mtd_part?? 表示MTD分區(qū),其中包含了 mtd_info,每一個分區(qū)都是被看成一個MTD 原始設備?
在mtd_table中,mtd_part.mtd_info中的大部分數(shù)據(jù)都從該分區(qū)的主分區(qū)mtd_part->master中獲得?
tip: master不作為一個mtd原始設備加入mtd_table
各層之間的交互如下圖
????
mtd_info的主要數(shù)據(jù)結構
| 域 | 作用 |
| type | mtd類型, 包括MTD_NORFLASH,MTD_NANDFLASH等(See mtd-abi.h) |
| flags | 標志位, MTD_WRITEABLE,MTD_NO_ERASE等(See mtd-abi.h) |
| size | mtd設備的大小 |
| erasesize | 主要的擦除大小, 即Flash的塊大小 (tip: mtd設備可能有多個erasesize) |
| writesize | 寫大小, 對于norFlash是字節(jié),對nandFlash為一頁 |
| oobsize | 每塊oob數(shù)據(jù)量, eg 16 |
| oobavail | ? |
| name | 命名 |
| index | ? |
| ecclayout | nand_ecclayout結構體指針, 表示的是ecc布局,可參考硬件手冊的OOB中ecc布局 |
| numeraseregions | 可變擦除區(qū)域的數(shù)目, 通常為1 |
| eraseregions | mtd_erase_region_info結構體指針, 可變擦除區(qū)域 |
| erase | 擦除Flash函數(shù) |
| read/write | 讀寫Flash函數(shù) |
| read_oob/write_oob | 帶oob讀寫Flash函數(shù) |
| suspend/resume | Power Management functions |
| priv | 私有數(shù)據(jù), cfi接口flash指向map_info結構, 或指向自定義flash相關結構體 |
| ? | ? |
mtd_part的主要數(shù)據(jù)結構
| 域 | 作用 |
| mtd | 分區(qū)信息, 大部分由master決定 |
| master | 分區(qū)的主分區(qū) |
| offset | 分區(qū)的偏移地址 |
| index | 分區(qū)號 (3.0后不存在該字段) |
| list | 將mtd_part鏈成一個鏈表mtd_partitons |
| ? | ? |
mtd_partition的主要數(shù)據(jù)結構
| 域 | 作用 |
| name | ? |
| size | ? |
| offset | ? |
| mask_flags | ? |
| ecclayout | ? |
| mtdp | ? |
| ? | ? |
map_info的主要數(shù)據(jù)結構
| 域 | 作用 |
| name | 名稱 |
| size | 大小 |
| phys | 物理地址 |
| bankwidth | 總線寬度(in octets) |
| virt | 虛擬地址,通常通過ioremap將物理地址進行映射得到 |
| read/copy_from/write/copy_to | 讀寫函數(shù) |
| map_priv_1/map_priv_2 | 驅動可用的私有數(shù)據(jù) |
| ? | ? |
nand_chip的主要數(shù)據(jù)結構
| 域 | 作用 |
| IO_ADDR_R/IO_ADDR_W | 讀/寫8根io線的地址 |
| read_byte/read_word | 從芯片讀一個字節(jié)/字 |
| read_buf/write_buf | 讀芯片讀取內容至緩沖區(qū)/將緩沖區(qū)內容寫入芯片 |
| verify_buf | ? |
| select_chip | ? |
| block_bad | 檢查是否壞塊 |
| block_markbad | 標識壞塊 |
| cmd_ctrl | 硬件相關控制函數(shù) |
| init_size | ? |
| dev_ready | ? |
| cmdfunc | 命令處理函數(shù) |
| waitfunc | ? |
| erase_cmd | 擦除命令 |
| scan_bbt | 掃描壞塊 |
| errstat | ? |
| write_page | ? |
| options | 與具體的NAND 芯片相關的選項, 如NAND_USE_FLASH_BBT等(nand.h) |
| page_shift | ? |
| ? | ? |
| ecclayout | nand_ecclayout類型結構體, ECC布局信息 |
| ecc | nand_ecc_ctrl類型結構體, ECC控制結構 |
| ? | ? |
| ? | ? |
| ? | ? |
nand_ecclayout的主要數(shù)據(jù)結構
| 域 | 作用 |
| eccbytes | ecc的字節(jié)數(shù)(For 512B-per-page, eccbytes is 3) |
| eccpos | ecc數(shù)據(jù)在oob中的位置 |
| oobavail | oob中可用的字節(jié)數(shù), MTD 會根據(jù)其它三個變量自動計算得到 |
| oobfree | nand_oobfree類型結構體, 顯示定義空閑的oob 字節(jié) |
| ? | ? |
MTD相關層實現(xiàn)
MTD設備層
mtd字符設備接口:?
mtdchar.c 實現(xiàn)了字符設備接口,通過它,用戶可以直接操作Flash 設備。?
? 通過read()、write()系統(tǒng)調用可以讀寫Flash。?
? 通過一系列IOCTL 命令可以獲取Flash 設備信息、擦除Flash、讀寫NAND 的OOB、獲取OOB layout 及檢查NAND 壞塊等(MEMGETINFO、MEMERASE、MEMREADOOB、MEMWRITEOOB、MEMGETBADBLOCK IOCRL)?
tip: mtd_read和mtd_write直接直接調用mtd_info的read 函數(shù),因此,字符設備接口跳過patition這一層
mtd塊設備接口:?
主要原理是將Flash的erase block 中的數(shù)據(jù)在內存中建立映射,然后對其進行修改,最后擦除Flash 上的block,將內存中的映射塊寫入Flash 塊。整個過程被稱為read/modify/erase/rewrite 周期。?
但是,這樣做是不安全的,當下列操作序列發(fā)生時,read/modify/erase/poweroff,就會丟失這個block 塊的數(shù)據(jù)。?
塊設備模擬驅動按照block 號和偏移量來定位文件,因此在Flash 上除了文件數(shù)據(jù),基本沒有額外的控制數(shù)據(jù)。
?
MTD原始設備層
?
MTD硬件驅動層
1. NOR Flash驅動結構
Linux系統(tǒng)實現(xiàn)了針對cfi,jedec等接口的通用NOR Flash驅動?
在上述接口驅動基礎上,芯片級驅動較簡單?
???? 定義具體內存映射結構體map_info,然后通過接口類型后調用do_map_probe()??
以h720x-flash.c為例(位于drivers/mtd/maps)?
- 定義map_info結構體, 初始化成員name, size, phys, bankwidth?
- 通過ioremap映射成員virt(虛擬內存地址)?
- 通過函數(shù)simple_map_init初始化map_info成員函數(shù)read,write,copy_from,copy_to?
- 調用do_map_probe進行cfi接口探測, 返回mtd_info結構體?
- 通過parse_mtd_partitions, add_mtd_partitions注冊mtd原始設備
2. NAND Flash驅動結構?
Linux實現(xiàn)了通用NAND驅動(drivers/mtd/nand/nand_base.c)?
tip: For more, check?內核中的NAND代碼布局??
芯片級驅動需要實現(xiàn)nand_chip結構體?
MTD使用nand_chip來表示一個NAND FLASH芯片, 該結構體包含了關于Nand Flash的地址信息,讀寫方法,ECC模式,硬件控制等一系列底層機制。?
? NAND芯片級初始化?
主要有以下幾個步驟:?
- 分配nand_chip內存,根據(jù)目標板及NAND控制器初始化nand_chip中成員函數(shù)(若未初始化則使用nand_base.c中的默認函數(shù)),將mtd_info中的priv指向nand_chip(或板相關私有結構),設置ecc模式及處理函數(shù)?
- 以mtd_info為參數(shù)調用nand_scan()探測NAND FLash。?
?? nand_scan()會讀取nand芯片ID,并根據(jù)mtd->priv即nand_chip中成員初始化mtd_info?
- 若有分區(qū),則以mtd_info和mtd_partition為參數(shù)調用add_mtd_partitions()添加分區(qū)信息?
-
? MTD對NAND芯片的讀寫?
主要分三部分:?
A、struct mtd_info中的讀寫函數(shù),如read,write_oob等,這是MTD原始設備層與FLASH硬件層之間的接口;?
B、struct nand_ecc_ctrl中的讀寫函數(shù),如read_page_raw,write_page等,主要用來做一些與ecc有關的操作;?
C、struct nand_chip中的讀寫函數(shù),如read_buf,cmdfunc等,與具體的NAND controller相關,就是這部分函數(shù)與硬件交互,通常需要我們自己來實現(xiàn)。?
tip: nand_chip中的讀寫函數(shù)雖然與具體的NAND controller相關,但是MTD也為我們提供了默認的讀寫函數(shù),如果NAND controller比較通用(使用PIO模式),那么對NAND芯片的讀寫與MTD提供的這些函數(shù)一致,就不必自己實現(xiàn)這些函數(shù)。
上面三部分讀寫函數(shù)相互配合完成對NAND芯片的讀寫?
首先,MTD上層需要讀寫NAND芯片時,會調用struct mtd_info中的讀寫函數(shù),接著struct mtd_info中的讀寫函數(shù)就會調用struct nand_chip或struct nand_ecc_ctrl中的讀寫函數(shù),最后,若調用的是struct nand_ecc_ctrl中的讀寫函數(shù),那么它又會接著調用struct nand_chip中的讀寫函數(shù)。?
eg:? 以讀為例?
MTD上層會調用struct mtd_info中的讀page函數(shù),即nand_read函數(shù)。?
接著nand_read函數(shù)會調用struct nand_chip中cmdfunc函數(shù),這個cmdfunc函數(shù)與具體的NAND controller相關,它的作用是使NAND controller向NAND 芯片發(fā)出讀命令,NAND芯片收到命令后,就會做好準備等待NAND controller下一步的讀取。?
接著nand_read函數(shù)又會調用struct nand_ecc_ctrl中的read_page函數(shù),而read_page函數(shù)又會調用struct nand_chip中read_buf函數(shù),從而真正把NAND芯片中的數(shù)據(jù)讀取到buffer中(所以這個read_buf的意思其實應該是read into buffer,另外,這個buffer是struct mtd_info中的nand_read函數(shù)傳下來的)。?
read_buf函數(shù)返回后,read_page函數(shù)就會對buffer中的數(shù)據(jù)做一些處理,比如校驗ecc,以及若數(shù)據(jù)有錯,就根據(jù)ecc對數(shù)據(jù)修正之類的,最后read_page函數(shù)返回到nand_read函數(shù)中。?
對NAND芯片的其它操作,如寫,擦除等,都與讀操作類似?
http://www.cnblogs.com/hzl6255/archive/2012/12/18/2824043.html
?
MTD(memory technology device內存技術設備)是用于訪問memory設備(ROM、flash)的Linux的子系統(tǒng)。MTD的主要目的是為了使新的memory設備的驅 動更加簡單,為此它在硬件和上層之間提供了一個抽象的接口。MTD的所有源代碼在/drivers/mtd子目錄下。我將CFI接口的MTD設備分為四層 (從設備節(jié)點直到底層硬件驅動),這四層從上到下依次是:設備節(jié)點、MTD設備層、MTD原始設備層和硬件驅動層。?
一、Flash硬件驅動層:硬件驅動層負責在init時驅動Flash硬件,Linux MTD設備的NOR Flash芯片驅動遵循CFI接口標準,其驅動程序位于drivers/mtd/chips子目錄下。NAND型Flash的驅動程 序則位于/drivers/mtd/nand子目錄下。
二、MTD原始設備:原始設備層有兩部分組成,一部分是MTD原始設備的通用代碼,另一部分是各個特定的Flash的數(shù)據(jù),例如分區(qū)。 用于描述MTD原始設備的數(shù)據(jù)結構是mtd_info,這其中定義了大量的關于MTD的數(shù)據(jù)和操作函數(shù)。mtd_table(mtdcore.c)則是所 有MTD原始設備的列表,mtd_part(mtd_part.c)是用于表示MTD原始設備分區(qū)的結構,其中包含了mtd_info,因為每一個分區(qū)都 是被看成一個MTD原始設備加在mtd_table中的,mtd_part.mtd_info中的大部分數(shù)據(jù)都從該分區(qū)的主分區(qū) mtd_part->master中獲得。 在drivers/mtd/maps/子目錄下存放的是特定的flash的數(shù)據(jù),每一個文件都描述了一塊板子上的flash。其中調用 add_mtd_device()、del_mtd_device()建立/刪除mtd_info結構并將其加入/刪除mtd_table(或者調用 add_mtd_partition()、del_mtd_partition()(mtdpart.c)建立/刪除mtd_part結構并將 mtd_part.mtd_info加入/刪除mtd_table 中)。?
三、MTD設備層:基于MTD原始設備,linux系統(tǒng)可以定義出MTD的塊設備(主設備號31)和字符設備(設備號90)。MTD字符設備的定義在 mtdchar.c中實現(xiàn),通過注冊一系列file operation函數(shù)(lseek、open、close、read、write)。MTD塊設備則是定義了一個描述MTD塊設備的結構 mtdblk_dev,并聲明了一個名為mtdblks的指針數(shù)組,這數(shù)組中的每一個mtdblk_dev和mtd_table中的每一個 mtd_info一一對應。?
四、設備節(jié)點:通過mknod在/dev子目錄下建立MTD字符設備節(jié)點(主設備號為90)和MTD塊設備節(jié)點(主設備號為31),通過訪問此設備節(jié)點即可訪問MTD字符設備和塊設備。?
五、根文件系統(tǒng):在Bootloader中將JFFS(或JFFS2)的文件系統(tǒng)映像jffs.image(或jffs2.img)燒到flash的 某一個分區(qū)中,在/arch/arm/mach-your/arch.c文件的your_fixup函數(shù)中將該分區(qū)作為根文件系統(tǒng)掛載。?
六、文件系統(tǒng):內核啟動后,通過mount 命令可以將flash中的其余分區(qū)作為文件系統(tǒng)掛載到mountpoint上。
http://www.cnblogs.com/hoys/archive/2012/05/30/2526230.html
?
//----------------------------------------------個人見解----------------------------------------
?
1、linux nandflash驅動主要工作在于nand_chip結構體填充(linux內核在MTD的下層實現(xiàn)了通用的nand驅動(主要通過drivers/mtd/nand_base.c文件實現(xiàn)),因此芯片級的nand驅動不再需要實現(xiàn)mtd_info中的read、write、read_oob等函數(shù),而主體轉移到了nand_chip數(shù)據(jù)結構體填充上)、內核flash分區(qū)表配置兩部分,而nand_chip結構體填充驅動一般芯片廠商提供的開發(fā)包中會有這個驅動,例如dm365的nand_chip結構體填充驅動就是drivers/mtd/nand/davinvi-nand.c
在davinvi-nand.c驅動中,會涉及到一個ecc布局的結構體struct?nand_ecclayout如下:
static struct nand_ecclayout hwecc4_small __initconst = {
.eccbytes = 10,
.eccpos = { 0, 1, 2, 3, 4,
/* offset 5 holds the badblock marker */
6, 7,
13, 14, 15, },
.oobfree = {
{.offset = 8, .length = 5, },
{.offset = 16, },
},
};
nand_ecclayout結構體指針, 表示的是ecc布局,可參考硬件手冊的OOB中ecc布局。
下面是相關的一些成員介紹:
?
struct nand_ecclayout {
uint32_t eccbytes; ? ?//表示使用幾個ecc字節(jié)
uint32_t eccpos[128]; //表示ecc占用的位置,因為現(xiàn)在大頁面4kbyte也就128個,所以這里寫了128,
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //以后有更大頁面的,這里也要改了。
uint32_t oobavail; ? ? ? //有幾個oob可用,這個跟下面的成員有點像,一般用下面的
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; ?//定義oob有效個數(shù),從哪開始等
};
?
?
給個例子:
?
static struct nand_ecclayout mylayout = {
#ifdef CONFIG_SYS_NAND_PAGE_2K
.eccbytes = 40,
.eccpos = {?
24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
59, 60, 61, 62, 63,?
},
.oobfree = {
{.offset = 2, .length = 22, },
},
#endif
}
?其中,.eccbytes = 40,跟初始化有關系,我們一般這樣初始化:
?
nand->ecc.size = 512;?
nand->ecc.bytes = 10;
恩,這下明朗了,我們需要每512個字節(jié)產生10個ecc字節(jié),因此對2kbyte頁面的flash來說,一頁就是4個512,因此需要4*10=40個ecc字節(jié)。
.eccpos就是告訴驅動,這些ecc字節(jié)放在哪里,一般是按順序存放,不要覆蓋芯片默認的壞塊標記位,對2kbyte的flash來說,廠家說是前兩個即第0、1個字節(jié)是壞塊標志。
所以分配為eccbytes和eccpos后,后面有個oobfree,這樣看來也很明白了:
offset=2表示從第2個字節(jié)開始(因為前面2個是壞塊標志啊~~),length=22表示(從offset開始)共22個ecc字節(jié)可以用戶隨便用。
這下一目了然了吧。
?
2、有了nand_chip結構體填充驅動了,接下來需要往系統(tǒng)注冊一個nand flash設備了,一般情況是在板級初始化的代碼中,一般目錄是arch/arm/mach****/****.c文件(或者也有可能在devices.c中),在這個文件中,一般會包括定義nandflash分區(qū)信息結構,注冊nandflash設備,其中還包括了定義一些IO資源,用于主控器驅動獲得IO資源配置相應的寄存器以及數(shù)據(jù)讀取。例如dm365的板級初始化文件:arch/arm/mach-davinci/board-dm365-evm.c中:
#define NAND_BLOCK_SIZE(SZ_16K)//32MB or 64MB
static struct mtd_partition nand_partitions[] = {
/* bootloader (UBL, U-Boot, BBT) in sectors: 0 - 14 */
{
.name = "bootloader",
.offset = 0,
.size = 32 * NAND_BLOCK_SIZE,
.mask_flags = MTD_WRITEABLE,/* force read-only */
},
/* bootloader params in the next sector 15 */
{
.name = "params",
.offset = MTDPART_OFS_APPEND,
.size = 96 * NAND_BLOCK_SIZE,
.mask_flags = MTD_WRITEABLE,/* force read-only */
},
/* kernel in sectors: 16 */
{
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_2M,
.mask_flags = 0
},
{
.name = "filesystem1",
.offset = MTDPART_OFS_APPEND,
.size = SZ_16M,//SZ_16M + SZ_8M,
.mask_flags = 0
},
{
.name = "filesystem2",
.offset = MTDPART_OFS_APPEND,
.size = SZ_2M,//SZ_8M,
.mask_flags = 0
},
{
.name = "Calibration",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
.mask_flags = 0
}
};
上面是nandflash分區(qū)信息定義結構體,在上面結構體中,總共為nandflash分成了6個區(qū),在系統(tǒng)啟動后,可以通過ls /dev/mtdblock*查看到所有的分區(qū),看到的mtdblock*設備文件節(jié)點從0開始分別對應上面數(shù)組中的六個分區(qū),如果需要使用哪個分區(qū),則可以通過mount掛載到文件系統(tǒng)中使用。也能通過系統(tǒng)啟動時打印的信息看到分區(qū)情況:
Creating 6 MTD partitions on "nand_davinci.0":
0x00000000-0x00080000 : "bootloader"
0x00080000-0x00200000 : "params"
0x00200000-0x00400000 : "kernel"
0x00400000-0x01400000 : "filesystem1"
0x01400000-0x01600000 : "filesystem2"
0x01600000-0x04000000 : "Calibration"
按照上面信息可以看出,文件系統(tǒng)是保存在0x00400000-0x01400000或者0x01400000-0x01600000地址段中(后面假設系統(tǒng)是只用filesystem1),內核是保存0x00200000-0x00400000地址段中,所以在燒錄內核時,應該使用nand write 0x80700000?0x00200000 0x00300000(其中0x00300000表示寫入大小,0x00200000表示寫入nandflash的起始地址,0x80700000表示從內存的這個地址讀出內核燒寫到對應的nandflash地址中),而燒錄文件可以通過網絡文件系統(tǒng)啟動板子,再將上面的filesystem1掛載在mnt/目錄下:mount /dev/mtdblock3 /mnt/mtd3,然后直接將要燒錄的文件系統(tǒng)解壓到這個filesystem1分區(qū)中,也能通過網絡上其它方式燒錄文件系統(tǒng),如yaffs jffs2等等,燒錢文件系統(tǒng)前,必須通過nand erase在uboot階段擦除這塊地址段中的flash數(shù)據(jù),如擦寫filesystem1的數(shù)據(jù)命令:nand erase?0x00400000 ********* (***表示擦寫塊大小)?
?
static struct resource nand_resources[] = {
[0] = {
/* First memory resource is AEMIF control registers */
.start = DM365_ASYNC_EMIF_CNTRL_BASE,
.end = DM365_ASYNC_EMIF_CNTRL_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
/* Second memory resource is NAND I/O window */
.start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
.end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[2] = {
/* Third (optional) memory resource is NAND I/O window */
/* for second NAND chip select */
.start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16K,
.end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + 2 * SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
};
上面數(shù)組中定義的是nandflash接口(一般接在EMIF上)的IO內存資源,需要注意的是,這個數(shù)組如何定義取決于nandflash驅動(drivers/mtd/nand/davinvi-nand.c)中代碼是如何使用這些資源的,比如說davinci-nand.c獲取資源是platform_get_resource(pdev, IORESOURCE_MEM, 0),而獲取的這個資源是用于控制寄存器配置的,則上面數(shù)組中0成員就必須是EMIF控制寄存器的IO內存地址,如果這個資源是用于訪問nandflash數(shù)據(jù)的,則0數(shù)組的成員就必須是EMIF數(shù)據(jù)寄存器。所以這個數(shù)組的定義需要配置davinci-nand.c驅動的編寫來更改。
轉載于:https://www.cnblogs.com/pengdonglin137/p/3467960.html
總結
以上是生活随笔為你收集整理的MTD NANDFLASH驱动相关知识介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET Web API自身对CO
- 下一篇: 期货一手多少钱啊?