NAND驅動分析 (一)

2021-08-09 16:24:21 字數 3955 閱讀 5958

因為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_initnand_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...