因為nand flash驅動是採用了mtd技術,所以首先對nand硬體驅動層進行分析(以ppc架構為例進行分析,nand flash採用了micron公司的512mb、2k頁大小、的flash晶元)。
ppc架構的cpu晶元並沒有整合專用的nand flash控制器,而是使用elbc(增強型本地匯流排控制器)的nand控制模式來對nand flash晶元進行控制的。所以首先分析nand底層硬體驅動,fsl_elbc_nand.c檔案。
drivers\mtd\nand\fsl_elbc_nand.c檔案:
linux系統在裝載底層硬體驅動時,會首先呼叫fsl_elbc_nand_init()函式。此函式的原始碼如下:
int
__init fsl_elbc_nand_init(void)
/*static int __devinit fsl_elbc_nand_probe(struct of_device *dev,
const struct of_device_id *match)*/
; struct mtd_partition *parts;
#endif
int ret;
int bank;
//struct device_node *node = dev->node;
printk("init elbc nand\n");
if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
return -enodev;
lbc = fsl_lbc_ctrl_dev->regs;
/* find which chip select it is connected to */
for (bank = 0; bank < max_banks; bank++)
if ((in_be32(&lbc->bank[bank].br) & br_v) &&
(in_be32(&lbc->bank[bank].br) & br_msel) == br_ms_fcm &&
(in_be32(&lbc->bank[bank].br) &
in_be32(&lbc->bank[bank].or) & br_ba)
== convert_lbc_address(lbc_sram_add_base))
break;
if (bank >= max_banks)
//priv = kzalloc(sizeof(*priv), gfp_kernel);
priv = kmalloc(sizeof(*priv), gfp_kernel);
if (!priv)
return -enomem;
memset(priv,0,sizeof(*priv));
if (fsl_lbc_ctrl_dev->nand == null)
elbc_fcm_ctrl->chips[bank] = priv;
priv->bank = bank;
priv->ctrl = fsl_lbc_ctrl_dev;
priv->vbase = ioremap(lbc_sram_add_base,lbc_sram_size);
if (!priv->vbase)
priv->mtd.name = pname;
if (!priv->mtd.name)
ret = fsl_elbc_chip_init(priv);
if (ret)
goto err;
priv->fmr |= (12
<< fmr_cwto_shift);
if (nand_scan (&priv->mtd, 1))
fsl_elbc_chip_init_tail(&priv->mtd);
add_mtd_partitions(&priv->mtd, p1020_partition_info, 3);
err:
//fsl_elbc_chip_remove(priv);
return ret;
}
其中elbc暫存器結構體和描述elbc的mtd資訊結構體如下所示:
struct fsl_lbc_regs __iomem *lbc; //elbc暫存器結構體
struct fsl_elbc_mtd *priv; //elbc的mtd資訊結構體
繼續往下分析,可以看到lbc = fsl_lbc_ctrl_dev->regs;由此可知,lbc的基位址是由fsl_lbc_ctrl_dev結構體中的regs成員賦予的,而fsl_lbc_ctrl_dev結構體的初始化**如下所示:
static __init int fsl_lbc_init(void)
fsl_lbc_ctrl_dev->irq =3+
64; //賦值中斷號
ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev); //初始化elbc的中斷相關等暫存器
if (ret <
0) goto err;
ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
"fsl-lbc", fsl_lbc_ctrl_dev); //註冊elbc的中斷函式
if (ret !=
0) return
0;err:
return ret;
}
有上述**可知,在fsl_elbc_nand_init()函式中的lbc其實是elbc暫存器的基位址,如果想對elbc的暫存器進行操作,直接對lbc進行賦值即可。
接下來回到fsl_elbc_nand_init()函式當中,繼續往下,會看到priv = kmalloc(sizeof(*priv), gfp_kernel);語句。此時將對priv結構體分配記憶體空間,並對priv的各個成員進行初始化操作。如以下**所示:
priv = kmalloc(sizeof(*priv), gfp_kernel); //為priv結構體分配記憶體空間
if (!priv)
return
-enomem;
memset(priv,0,sizeof(*priv));
if (fsl_lbc_ctrl_dev->nand ==
null) //判斷nand成員是否為空,如果是則執行如下**。事實證明nand成員確實為空。
elbc_fcm_ctrl->chips[bank]
= priv; //再將priv結構指標賦值給elbc_fcm_ctrl的chips成員。
priv->bank = bank; //得到nand flash的片選訊號數值編號。
priv->ctrl = fsl_lbc_ctrl_dev; //最後再將控制器結構體fsl_lbc_ctrl_dev指標賦值給ctrl。
繼續往下分析,可以看到呼叫了ret = fsl_elbc_chip_init(priv);函式。此函式用於初始化priv結構體中的nand_chip成員,而此成員中的一些函式就是代表了對nand flash晶元的一些基本操作,如:寫命令、讀資料和寫位址等。而**最後還將呼叫nand_scan (&priv->mtd, 1)函式,來掃瞄nand裝置並對mtd結構進行新建和初始化。
而對fsl_elbc_chip_init和nand_scan函式的分析,將放到下一章來進行分析。
日記 nand驅動移植簡介
友善原始檔可以移植成功,先寫過程吧!1.拷貝s3c nand.c到適當目錄下,修改makefile,kconfig,對比友善的。我使用beyond compare,真棒的軟體。2.regs nand.h要拷貝,包括一些預定義。在三個目錄之中某乙個,plat samsung,plat s5p,或mac...
NAND控制器驅動測試方法
md test node v0.1 2014.12.7 draft 當完成乙個linux的nand flash controller驅動時,可以使用核心中提供的測試 去測試 你寫的驅動。實際上當你寫的nand flash controller驅動想上傳到linux kernel的主線 時,maint...
基於linux2 6 16的nand驅動開發(二)
第二部分 具體的nand flash驅動 搞清楚了mtd,核心,nandflash裝置驅動的關係後,現在就是如何編寫針對我們這款處理器的驅動,首先介紹一下nandflash結構struct nand chip struct nand chip void iomem io addr r 這是nandf...