塊裝置驅動(3)——nand flash驅動
/* 參考 * drivers\mtd\nand\s3c2410.c * drivers\mtd\nand\at91_nand.c */ #include <linux/module.h> #include <linux/types.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/ioport.h> #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/slab.h> #include <linux/clk.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> #include <asm/io.h> #include <asm/arch/regs-nand.h> #include <asm/arch/nand.h> struct s3c_nand_regs { unsigned long nfconf ; unsigned long nfcont ; unsigned long nfcmd ; unsigned long nfaddr ; unsigned long nfdata ; unsigned long nfeccd0 ; unsigned long nfeccd1 ; unsigned long nfeccd ; unsigned long nfstat ; unsigned long nfestat0; unsigned long nfestat1; unsigned long nfmecc0 ; unsigned long nfmecc1 ; unsigned long nfsecc ; unsigned long nfsblk ; unsigned long nfeblk ; }; static struct nand_chip *s3c_nand; static struct mtd_info *s3c_mtd; static struct s3c_nand_regs *s3c_nand_regs; static struct mtd_partition s3c_nand_parts[] = { [0] = { .name = "bootloader", .size = 0x00040000, .offset = 0, }, [1] = { .name = "params", .offset = MTDPART_OFS_APPEND, .size = 0x00020000, }, [2] = { .name = "kernel", .offset = MTDPART_OFS_APPEND, .size = 0x00200000, }, [3] = { .name = "root", .offset = MTDPART_OFS_APPEND, .size = MTDPART_SIZ_FULL, } }; static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr) { if (chipnr == -1) { /* 取消選中: NFCONT[1]設為1 */ s3c_nand_regs->nfcont |= (1<<1); } else { /* 選中: NFCONT[1]設為0 */ s3c_nand_regs->nfcont &= ~(1<<1); } } static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) { if (ctrl & NAND_CLE) { /* 發命令: NFCMMD=dat */ s3c_nand_regs->nfcmd = dat; } else { /* 發地址: NFADDR=dat */ s3c_nand_regs->nfaddr = dat; } } static int s3c2440_dev_ready(struct mtd_info *mtd) { return (s3c_nand_regs->nfstat & (1<<0)); } static int s3c_nand_init(void) { struct clk *clk; /* 1. 分配一個nand_chip結構體 */ s3c_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); s3c_nand_regs = ioremap(0x4E000000, sizeof(struct s3c_nand_regs)); /* 2. 設定nand_chip */ /* 設定nand_chip是給nand_scan函式使用的, 如果不知道怎麼設定, 先看nand_scan怎麼使用 * 它應該提供:選中,發命令,發地址,發資料,讀資料,判斷狀態的功能 */ s3c_nand->select_chip = s3c2440_select_chip; s3c_nand->cmd_ctrl = s3c2440_cmd_ctrl; s3c_nand->IO_ADDR_R = &s3c_nand_regs->nfdata; s3c_nand->IO_ADDR_W = &s3c_nand_regs->nfdata; s3c_nand->dev_ready = s3c2440_dev_ready; s3c_nand->ecc.mode = NAND_ECC_SOFT; /* 3. 硬體相關的設定: 根據NAND FLASH的手冊設定時間引數 */ /* 使能NAND FLASH控制器的時鐘 */ clk = clk_get(NULL, "nand"); clk_enable(clk); /* CLKCON'bit[4] */ /* HCLK=100MHz * TACLS: 發出CLE/ALE之後多長時間才發出nWE訊號, 從NAND手冊可知CLE/ALE與nWE可以同時發出,所以TACLS=0 * TWRPH0: nWE的脈衝寬度, HCLK x ( TWRPH0 + 1 ), 從NAND手冊可知它要>=12ns, 所以TWRPH0>=1 * TWRPH1: nWE變為高電平後多長時間CLE/ALE才能變為低電平, 從NAND手冊可知它要>=5ns, 所以TWRPH1>=0 */ #define TACLS 0 #define TWRPH0 1 #define TWRPH1 0 s3c_nand_regs->nfconf = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4); /* NFCONT: * BIT1-設為1, 取消片選 * BIT0-設為1, 使能NAND FLASH控制器 */ s3c_nand_regs->nfcont = (1<<1) | (1<<0); /* 4. 使用: nand_scan */ s3c_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); s3c_mtd->owner = THIS_MODULE; s3c_mtd->priv = s3c_nand; nand_scan(s3c_mtd, 1); /* 識別NAND FLASH, 構造mtd_info */ /* 5. add_mtd_partitions */ add_mtd_partitions(s3c_mtd, s3c_nand_parts, 4); //add_mtd_device(s3c_mtd); return 0; } static void s3c_nand_exit(void) { del_mtd_partitions(s3c_mtd); kfree(s3c_mtd); iounmap(s3c_nand_regs); kfree(s3c_nand); } module_init(s3c_nand_init); module_exit(s3c_nand_exit); MODULE_LICENSE("GPL");
程式碼出自“韋東山視訊”。
1、make menuconfig去掉核心中已選的nand flash驅動
-> Device Drivers
-> Memory Technology Device (MTD) support
-> NAND Device Support
< > NAND Flash support for S3C2410/S3C2440 SoC
2、製作新的核心make uImage
3、nfs啟動檔案系統
(1)uboot設定啟動引數,開發板ip=192.168.7.17,nfs server虛擬機器ip=192.168.7.120,nfs目錄/work/nfs_root/rootfs
set bootargs noinitrd root=/dev/nfs nfsroot=192.168.7.120:/work/nfs_root/rootfs ip=192.168.7.17:192.168.7.120:192.168.7.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0
儲存設定,save
(2)在開發板上ping 192.168.7.120,保證網路暢通
(3)在虛擬機器上編輯檔案系統的配置引數,/work/nfs_root/rootfs/etc/init.d/rcS,設定ip=192.168.7.17
(4)啟動新的核心
tftp 30000000 uImage
bootm 30000000
4、安裝驅動,insmod s3c_nand.ko,即可看到四個分割槽
5、掛接檔案系統,mount -t yaffs /dev/mtdblock3 /mnt,預設yaffs檔案系統
掛載上之後即可看到原來nand flash上root分割槽的內容
6、製作格式化工具
(1) tar xjf mtd-utils-05.07.23.tar.bz2
(2)cd mtd-utils-05.07.23/util
修改Makefile:
#CROSS=arm-linux-
改為
CROSS=arm-linux-
(3) make
(4)cp flash_erase flash_eraseall /work/nfs_root/rootfs/bin/
7、格式化root分割槽,格式化後原來root分割槽的內容就沒有了,/mnt目錄為空,預設為yaffs檔案系統
flash_eraseall /dev/mtd3
mount -t yaffs /dev/mtdblock3 /mnt
在/mnt下新建目錄、檔案,重新上電,進行測試