MTD NAND 驅動程式設計介面

作者:

Thomas Gleixner

簡介

通用 NAND 驅動程式支援幾乎所有基於 NAND 和 AG-AND 的晶片,並將它們連線到 Linux 核心的記憶體技術裝置 (MTD) 子系統。

本文件提供給想要實現適用於 NAND 裝置的板級驅動程式或檔案系統驅動程式的開發人員。

已知錯誤和假設

無。

文件提示

函式和結構文件是自動生成的。每個函式和結構成員都有一個簡短的描述,並標有 [XXX] 識別符號。以下章節解釋了這些識別符號的含義。

函式識別符號 [XXX]

這些函式在簡短的註釋中用 [XXX] 識別符號標記。這些識別符號解釋了函式的使用和範圍。使用以下識別符號

  • [MTD 介面]

    這些函式提供了 MTD 核心 API 的介面。它們不可替換,並提供完全獨立於硬體的功能。

  • [NAND 介面]

    這些函式已匯出,並提供 NAND 核心 API 的介面。

  • [GENERIC]

    通用函式不可替換,並提供完全獨立於硬體的功能。

  • [DEFAULT]

    預設函式提供與硬體相關的功能,適用於大多數實現。如果需要,板級驅動程式可以替換這些函式。這些函式透過 NAND 晶片描述結構中的指標呼叫。板級驅動程式可以在呼叫 nand_scan() 之前設定應由板級相關函式替換的函式。如果在進入 nand_scan() 時函式指標為 NULL,則該指標將設定為適用於檢測到的晶片型別的預設函式。

結構成員識別符號 [XXX]

結構成員在註釋中用 [XXX] 識別符號標記。這些識別符號解釋了成員的使用和範圍。使用以下識別符號

  • [INTERN]

    這些成員僅供 NAND 驅動程式內部使用,不得修改。這些值中的大多數都是從晶片幾何資訊計算出來的,這些資訊在 nand_scan() 期間進行評估。

  • [REPLACEABLE]

    可替換成員儲存硬體相關函式,這些函式可由板級驅動程式提供。板級驅動程式可以在呼叫 nand_scan() 之前設定應由板級相關函式替換的函式。如果在進入 nand_scan() 時函式指標為 NULL,則該指標將設定為適用於檢測到的晶片型別的預設函式。

  • [BOARDSPECIFIC]

    板級特定成員儲存硬體相關資訊,這些資訊必須由板級驅動程式提供。板級驅動程式必須在呼叫 nand_scan() 之前設定函式指標和資料欄位。

  • [OPTIONAL]

    可選成員可以儲存與板級驅動程式相關的資訊。通用 NAND 驅動程式程式碼不使用此資訊。

基本板級驅動程式

對於大多數板,僅提供基本函式並填寫 NAND 晶片描述結構中一些真正與板相關的成員就足夠了。

基本定義

至少您必須提供一個 nand_chip 結構和一個用於儲存 ioremap'ed 晶片地址的儲存。您可以使用 kmalloc 分配 nand_chip 結構,也可以靜態分配它。NAND 晶片結構嵌入一個 mtd 結構,該結構將註冊到 MTD 子系統。您可以使用 nand_to_mtd() 助手從 nand_chip 指標中提取指向 mtd 結構的指標。

基於 Kmalloc 的示例

static struct mtd_info *board_mtd;
static void __iomem *baseaddr;

靜態示例

static struct nand_chip board_chip;
static void __iomem *baseaddr;

分割槽定義

如果您想將您的裝置劃分為分割槽,請定義一個適合您板的分割槽方案。

#define NUM_PARTITIONS 2
static struct mtd_partition partition_info[] = {
    { .name = "Flash partition 1",
      .offset =  0,
      .size =    8 * 1024 * 1024 },
    { .name = "Flash partition 2",
      .offset =  MTDPART_OFS_NEXT,
      .size =    MTDPART_SIZ_FULL },
};

硬體控制函式

硬體控制函式提供對 NAND 晶片控制引腳的訪問。可以透過 GPIO 引腳或地址線完成訪問。如果您使用地址線,請確保滿足時序要求。

基於 GPIO 的示例

static void board_hwcontrol(struct mtd_info *mtd, int cmd)
{
    switch(cmd){
        case NAND_CTL_SETCLE: /* Set CLE pin high */ break;
        case NAND_CTL_CLRCLE: /* Set CLE pin low */ break;
        case NAND_CTL_SETALE: /* Set ALE pin high */ break;
        case NAND_CTL_CLRALE: /* Set ALE pin low */ break;
        case NAND_CTL_SETNCE: /* Set nCE pin low */ break;
        case NAND_CTL_CLRNCE: /* Set nCE pin high */ break;
    }
}

基於地址線的示例。 假設 nCE 引腳由晶片選擇解碼器驅動。

static void board_hwcontrol(struct mtd_info *mtd, int cmd)
{
    struct nand_chip *this = mtd_to_nand(mtd);
    switch(cmd){
        case NAND_CTL_SETCLE: this->legacy.IO_ADDR_W |= CLE_ADRR_BIT;  break;
        case NAND_CTL_CLRCLE: this->legacy.IO_ADDR_W &= ~CLE_ADRR_BIT; break;
        case NAND_CTL_SETALE: this->legacy.IO_ADDR_W |= ALE_ADRR_BIT;  break;
        case NAND_CTL_CLRALE: this->legacy.IO_ADDR_W &= ~ALE_ADRR_BIT; break;
    }
}

裝置就緒函式

如果硬體介面將 NAND 晶片的就緒繁忙引腳連線到 GPIO 或其他可訪問的 I/O 引腳,則使用此函式來讀取引腳的狀態。該函式沒有引數,如果裝置繁忙(R/B 引腳為低電平),則應返回 0,如果裝置就緒(R/B 引腳為高電平),則應返回 1。如果硬體介面無法訪問就緒繁忙引腳,則不得定義該函式,並且函式指標 this->legacy.dev_ready 設定為 NULL。

Init 函式

Init 函式分配記憶體並設定所有特定於板的引數和函式指標。當所有設定完成後,將呼叫 nand_scan()。此函式嘗試檢測和識別晶片。如果找到晶片,則會相應地初始化所有內部資料欄位。必須首先將結構清零,然後用有關裝置的必要資訊填充。

static int __init board_init (void)
{
    struct nand_chip *this;
    int err = 0;

    /* Allocate memory for MTD device structure and private data */
    this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
    if (!this) {
        printk ("Unable to allocate NAND MTD device structure.\n");
        err = -ENOMEM;
        goto out;
    }

    board_mtd = nand_to_mtd(this);

    /* map physical address */
    baseaddr = ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
    if (!baseaddr) {
        printk("Ioremap to access NAND chip failed\n");
        err = -EIO;
        goto out_mtd;
    }

    /* Set address of NAND IO lines */
    this->legacy.IO_ADDR_R = baseaddr;
    this->legacy.IO_ADDR_W = baseaddr;
    /* Reference hardware control function */
    this->hwcontrol = board_hwcontrol;
    /* Set command delay time, see datasheet for correct value */
    this->legacy.chip_delay = CHIP_DEPENDEND_COMMAND_DELAY;
    /* Assign the device ready function, if available */
    this->legacy.dev_ready = board_dev_ready;
    this->eccmode = NAND_ECC_SOFT;

    /* Scan to find existence of the device */
    if (nand_scan (this, 1)) {
        err = -ENXIO;
        goto out_ior;
    }

    add_mtd_partitions(board_mtd, partition_info, NUM_PARTITIONS);
    goto out;

out_ior:
    iounmap(baseaddr);
out_mtd:
    kfree (this);
out:
    return err;
}
module_init(board_init);

Exit 函式

只有當驅動程式編譯為模組時,才需要退出函式。它釋放晶片驅動程式持有的所有資源,並取消註冊 MTD 層中的分割槽。

#ifdef MODULE
static void __exit board_cleanup (void)
{
    /* Unregister device */
    WARN_ON(mtd_device_unregister(board_mtd));
    /* Release resources */
    nand_cleanup(mtd_to_nand(board_mtd));

    /* unmap physical address */
    iounmap(baseaddr);

    /* Free the MTD device structure */
    kfree (mtd_to_nand(board_mtd));
}
module_exit(board_cleanup);
#endif

高階板級驅動程式函式

本章介紹 NAND 驅動程式的高階功能。有關可由板級驅動程式覆蓋的函式列表,請參閱 nand_chip 結構的文件。

多晶片控制

nand 驅動程式可以控制晶片陣列。因此,板級驅動程式必須提供自己的 select_chip 函式。此函式必須(取消)選擇請求的晶片。必須在呼叫 nand_scan() 之前設定 nand_chip 結構中的函式指標。nand_scan() 的 maxchip 引數定義要掃描的最大晶片數。確保 select_chip 函式可以處理請求的晶片數。

nand 驅動程式將晶片連線到一個虛擬晶片,並將此虛擬晶片提供給 MTD 層。

注意:驅動程式只能處理大小相等的晶片的線性晶片陣列。不支援擴充套件匯流排寬度的並行陣列。

基於 GPIO 的示例

static void board_select_chip (struct mtd_info *mtd, int chip)
{
    /* Deselect all chips, set all nCE pins high */
    GPIO(BOARD_NAND_NCE) |= 0xff;
    if (chip >= 0)
        GPIO(BOARD_NAND_NCE) &= ~ (1 << chip);
}

基於地址線的示例。 假設 nCE 引腳連線到地址解碼器。

static void board_select_chip (struct mtd_info *mtd, int chip)
{
    struct nand_chip *this = mtd_to_nand(mtd);

    /* Deselect all chips */
    this->legacy.IO_ADDR_R &= ~BOARD_NAND_ADDR_MASK;
    this->legacy.IO_ADDR_W &= ~BOARD_NAND_ADDR_MASK;
    switch (chip) {
    case 0:
        this->legacy.IO_ADDR_R |= BOARD_NAND_ADDR_CHIP0;
        this->legacy.IO_ADDR_W |= BOARD_NAND_ADDR_CHIP0;
        break;
    ....
    case n:
        this->legacy.IO_ADDR_R |= BOARD_NAND_ADDR_CHIPn;
        this->legacy.IO_ADDR_W |= BOARD_NAND_ADDR_CHIPn;
        break;
    }
}

硬體 ECC 支援

函式和常量

nand 驅動程式支援三種不同型別的硬體 ECC。

  • NAND_ECC_HW3_256

    硬體 ECC 生成器,每 256 位元組提供 3 位元組 ECC。

  • NAND_ECC_HW3_512

    硬體 ECC 生成器,每 512 位元組提供 3 位元組 ECC。

  • NAND_ECC_HW6_512

    硬體 ECC 生成器,每 512 位元組提供 6 位元組 ECC。

  • NAND_ECC_HW8_512

    硬體 ECC 生成器,每 512 位元組提供 8 位元組 ECC。

如果您的硬體生成器具有不同的功能,請將其新增到 nand_base.c 中的適當位置

板級驅動程式必須提供以下函式

  • enable_hwecc

    在讀取/寫入晶片之前呼叫此函式。在此函式中重置或初始化硬體生成器。該函式使用一個引數呼叫,該引數允許您區分讀取和寫入操作。

  • calculate_ecc

    從/向晶片讀取/寫入後呼叫此函式。將 ECC 從硬體傳輸到緩衝區。如果設定了選項 NAND_HWECC_SYNDROME,則僅在寫入時呼叫該函式。見下文。

  • correct_data

    如果發生 ECC 錯誤,則呼叫此函式進行錯誤檢測和糾正。如果可以糾正錯誤,則分別返回 1 或 2。如果錯誤無法糾正,則返回 -1。如果您的硬體生成器與 nand_ecc 軟體生成器的預設演算法匹配,則使用 nand_ecc 提供的糾正函式,而不是實現重複程式碼。

帶有綜合徵計算的硬體 ECC

許多硬體 ECC 實現提供 Reed-Solomon 程式碼,並在讀取時計算錯誤綜合徵。在通用 Reed-Solomon 庫中呼叫錯誤糾正程式碼之前,必須將綜合徵轉換為標準 Reed-Solomon 綜合徵。

為了使綜合徵生成器工作,ECC 位元組必須緊隨資料位元組之後。這與軟體 ECC 通常使用的佈局相反。不再可能分離資料和帶外區域。nand 驅動程式程式碼處理此佈局,並且 oob 區域中剩餘的空閒位元組由自動放置程式碼管理。在這種情況下,提供一個匹配的 oob 佈局。有關實現參考,請參閱 rts_from4.c 和 diskonchip.c。在這些情況下,我們還必須在 FLASH 上使用壞塊表,因為 ECC 佈局會干擾壞塊標記位置。有關詳細資訊,請參閱壞塊表支援。

壞塊表支援

大多數 NAND 晶片在備用區域中的定義位置標記壞塊。在任何情況下都不得擦除這些塊,因為壞塊資訊將丟失。每次訪問塊時,都可以透過讀取塊中第一頁的備用區域來檢查壞塊標記。這很耗時,因此使用壞塊表。

nand 驅動程式支援各種型別的壞塊表。

  • 每個裝置

    壞塊表包含裝置的所有壞塊資訊,該裝置可以由多個晶片組成。

  • 每個晶片

    每個晶片使用一個壞塊表,幷包含此特定晶片的壞塊資訊。

  • 固定偏移

    壞塊表位於晶片(裝置)中的固定偏移處。這適用於各種 DiskOnChip 裝置。

  • 自動放置

    壞塊表自動放置並檢測在晶片(裝置)的末尾或開頭

  • 映象表

    壞塊表映象在晶片(裝置)上,以允許在不丟失資料的情況下更新壞塊表。

nand_scan() 呼叫函式 nand_default_bbt()。nand_default_bbt() 根據 nand_scan() 檢索到的晶片資訊選擇合適的預設壞塊表描述符。

標準策略是掃描裝置中的壞塊並構建一個基於 ram 的壞塊表,該表允許比始終檢查快閃記憶體晶片本身的壞塊資訊更快的訪問。

基於快閃記憶體的表

可能需要或必須將壞塊表儲存在 FLASH 中。對於 AG-AND 晶片,這是強制性的,因為它們沒有工廠標記的壞塊。它們有工廠標記的好塊。當擦除該塊以重新使用時,標記模式會被擦除。因此,如果在將模式寫回晶片之前斷電,則該塊將丟失並新增到壞塊中。因此,當第一次檢測到晶片時,我們會掃描晶片的好塊,並將此資訊儲存在壞塊表中,然後再擦除任何塊。

儲存表的塊受到保護,防止意外訪問,方法是在記憶體壞塊表中將它們標記為壞塊。壞塊表管理功能允許規避此保護。

啟用基於 FLASH 的壞塊表支援的最簡單方法是在呼叫 nand_scan() 之前在 nand 晶片結構的 bbt_option 欄位中設定選項 NAND_BBT_USE_FLASH。對於 AG-AND 晶片,預設情況下會這樣做。這將啟用 NAND 驅動程式的預設基於 FLASH 的壞塊表功能。預設的壞塊表選項是

  • 儲存每個晶片的壞塊表

  • 每個塊使用 2 位

  • 在晶片末尾自動放置

  • 使用帶有版本號的映象表

  • 在晶片末尾保留 4 個塊

使用者定義的表

使用者定義的表是透過填寫 nand_bbt_descr 結構並在呼叫 nand_scan() 之前將指標儲存在 nand_chip 結構成員 bbt_td 中來建立的。如果需要映象表,則必須建立第二個結構,並且指向該結構的指標必須儲存在 nand_chip 結構中的 bbt_md 中。如果 bbt_md 成員設定為 NULL,則僅使用主表,並且不執行映象表的掃描。

nand_bbt_descr 結構中最重要的欄位是 options 欄位。選項定義了大多數表屬性。使用 rawnand.h 中預定義的常量來定義選項。

  • 每個塊的位數

    支援的位數是 1、2、4、8。

  • 每個晶片的表

    設定常量 NAND_BBT_PERCHIP 選擇為晶片陣列中的每個晶片管理一個壞塊表。如果未設定此選項,則使用每個裝置的壞塊表。

  • 表位置是絕對的

    使用選項常量 NAND_BBT_ABSPAGE 並定義壞塊表在 pages 欄位中開始的絕對頁碼。如果您選擇了每個晶片的壞塊表並且您有一個多晶片陣列,則必須為晶片陣列中的每個晶片提供起始頁。注意:不執行表標識模式的掃描,因此欄位 pattern、veroffs、offs、len 可以保持未初始化

  • 表位置是自動檢測的

    該表可以位於晶片(裝置)的第一個或最後一個好塊中。設定 NAND_BBT_LASTBLOCK 以將壞塊表放置在晶片(裝置)的末尾。壞塊表透過儲存在儲存壞塊表的塊中第一頁的備用區域中的模式進行標記和標識。將指向模式的指標儲存在 pattern 欄位中。此外,模式的長度必須儲存在 len 中,並且備用區域中的偏移必須在 nand_bbt_descr 結構的 offs 成員中給出。對於映象壞塊表,強制使用不同的模式。

  • 表建立

    如果在掃描期間找不到表,則設定選項 NAND_BBT_CREATE 以啟用表建立。通常,如果找到新晶片,則僅執行一次此操作。

  • 表寫入支援

    設定選項 NAND_BBT_WRITE 以啟用表寫入支援。這允許在由於磨損而必須將塊標記為壞塊的情況下更新壞塊表。MTD 介面函式 block_markbad 正在呼叫壞塊表的更新函式。如果啟用了寫入支援,則表會在 FLASH 上更新。

    注意:僅應為帶有版本控制的映象表啟用寫入支援。

  • 表版本控制

    設定選項 NAND_BBT_VERSION 以啟用表版本控制。強烈建議為帶有寫入支援的映象表啟用此功能。它可以確保將丟失壞塊表資訊的風險降低到丟失有關應標記為壞塊的一個磨損塊的資訊。

  • 在寫入時儲存塊內容

    如果儲存壞塊表的塊確實包含其他有用資訊,請設定選項 NAND_BBT_SAVECONTENT。寫入壞塊表時,會讀取整個塊,更新壞塊表,擦除塊,然後將所有內容寫回。如果未設定此選項,則僅寫入壞塊表,並且忽略並擦除塊中的所有其他內容。

  • 保留塊數

    對於自動放置,必須為壞塊表儲存保留一些塊。保留塊的數量在壞塊表描述結構的 maxblocks 成員中定義。為映象表保留 4 個塊應該是一個合理的數字。這也限制了掃描壞塊表標識模式的塊的數量。

備用區域(自動)放置

nand 驅動程式實現了在備用區域中放置檔案系統資料的不同可能性,

  • 由 fs 驅動程式定義的放置

  • 自動放置

預設放置函式是自動放置。nand 驅動程式具有適用於各種晶片型別的內建預設放置方案。如果由於硬體 ECC 功能而導致預設放置不合適,則板級驅動程式可以提供自己的放置方案。

檔案系統驅動程式可以提供自己的放置方案,該方案將代替預設放置方案使用。

放置方案由 nand_oobinfo 結構定義

struct nand_oobinfo {
    int useecc;
    int eccbytes;
    int eccpos[24];
    int oobfree[8][2];
};
  • useecc

    useecc 成員控制 ecc 和放置函式。標頭檔案 include/mtd/mtd-abi.h 包含用於選擇 ecc 和放置的常量。MTD_NANDECC_OFF 完全關閉 ecc。不建議這樣做,僅可用於測試和診斷。MTD_NANDECC_PLACE 選擇呼叫方定義的放置,MTD_NANDECC_AUTOPLACE 選擇自動放置。

  • eccbytes

    eccbytes 成員定義每頁的 ecc 位元組數。

  • eccpos

    eccpos 陣列儲存備用區域中放置 ecc 程式碼的位元組偏移量。

  • oobfree

    oobfree 陣列定義備用區域中可用於自動放置的區域。該資訊以 {offset, size} 格式給出。offset 定義了可用區域的開始,size 定義了以位元組為單位的長度。可以定義多個區域。該列表以 {0, 0} 條目終止。

由 fs 驅動程式定義的放置

呼叫函式提供指向定義 ecc 放置的 nand_oobinfo 結構的指標。對於寫入,呼叫方必須提供備用區域緩衝區以及資料緩衝區。備用區域緩衝區大小為(頁數)*(備用區域的大小)。對於讀取,緩衝區大小為(頁數)*((備用區域的大小)+(每頁的 ecc 步驟數)* sizeof (int))。驅動程式將每個元組的 ecc 檢查結果儲存在備用緩衝區中。儲存順序是

<spare data page 0><ecc result 0>...<ecc result n>

...

<spare data page n><ecc result 0>...<ecc result n>

這是 YAFFS1 使用的傳統模式。

如果備用區域緩衝區為 NULL,則僅根據 nand_oobinfo 結構中給定的方案進行 ECC 放置。

自動放置

自動放置使用內建預設值將 ecc 位元組放置在備用區域中。如果必須將檔案系統資料儲存/讀取到備用區域中,則呼叫函式必須提供緩衝區。每頁的緩衝區大小由 nand_oobinfo 結構中的 oobfree 陣列確定。

如果備用區域緩衝區為 NULL,則僅根據預設的內建方案進行 ECC 放置。

備用區域自動放置預設方案

256 位元組頁大小

偏移量

內容

評論

0x00

ECC 位元組 0

錯誤糾正程式碼位元組 0

0x01

ECC 位元組 1

錯誤糾正程式碼位元組 1

0x02

ECC 位元組 2

錯誤糾正程式碼位元組 2

0x03

自動放置 0

0x04

自動放置 1

0x05

壞塊標記

如果此位元組中的任何位為零,則此塊為壞塊。這僅適用於塊中的第一頁。在剩餘的頁面中,此位元組保留

0x06

自動放置 2

0x07

自動放置 3

512 位元組頁大小

偏移量

內容

評論

0x00

ECC 位元組 0

此頁中較低 256 位元組資料的錯誤糾正程式碼位元組 0

0x01

ECC 位元組 1

此頁中較低 256 位元組資料的錯誤糾正程式碼位元組 1

0x02

ECC 位元組 2

此頁中較低 256 位元組資料的錯誤糾正程式碼位元組 2

0x03

ECC 位元組 3

此頁中較高 256 位元組資料的錯誤糾正程式碼位元組 0

0x04

已保留

已保留

0x05

壞塊標記

如果此位元組中的任何位為零,則此塊為壞塊。這僅適用於塊中的第一頁。在剩餘的頁面中,此位元組保留

0x06

ECC 位元組 4

此頁資料中上面 256 位元組資料的糾錯碼位元組 1

0x07

ECC 位元組 5

此頁資料中上面 256 位元組資料的糾錯碼位元組 2

0x08 - 0x0F

自動放置 0 - 7

2048 位元組頁大小

偏移量

內容

評論

0x00

壞塊標記

如果此位元組中的任何位為零,則此塊為壞塊。這僅適用於塊中的第一頁。在剩餘的頁面中,此位元組保留

0x01

保留

保留

0x02-0x27

自動放置 0 - 37

0x28

ECC 位元組 0

此頁第一個 256 位元組資料的糾錯碼位元組 0

0x29

ECC 位元組 1

此頁第一個 256 位元組資料的糾錯碼位元組 1

0x2A

ECC 位元組 2

此頁第一個 256 位元組資料的糾錯碼位元組 2

0x2B

ECC 位元組 3

此頁第二個 256 位元組資料的糾錯碼位元組 0

0x2C

ECC 位元組 4

此頁第二個 256 位元組資料的糾錯碼位元組 1

0x2D

ECC 位元組 5

此頁第二個 256 位元組資料的糾錯碼位元組 2

0x2E

ECC 位元組 6

此頁第三個 256 位元組資料的糾錯碼位元組 0

0x2F

ECC 位元組 7

此頁第三個 256 位元組資料的糾錯碼位元組 1

0x30

ECC 位元組 8

此頁第三個 256 位元組資料的糾錯碼位元組 2

0x31

ECC 位元組 9

此頁第四個 256 位元組資料的糾錯碼位元組 0

0x32

ECC 位元組 10

此頁第四個 256 位元組資料的糾錯碼位元組 1

0x33

ECC 位元組 11

此頁第四個 256 位元組資料的糾錯碼位元組 2

0x34

ECC 位元組 12

此頁第五個 256 位元組資料的糾錯碼位元組 0

0x35

ECC 位元組 13

此頁第五個 256 位元組資料的糾錯碼位元組 1

0x36

ECC 位元組 14

此頁第五個 256 位元組資料的糾錯碼位元組 2

0x37

ECC 位元組 15

此頁第六個 256 位元組資料的糾錯碼位元組 0

0x38

ECC 位元組 16

此頁第六個 256 位元組資料的糾錯碼位元組 1

0x39

ECC 位元組 17

此頁第六個 256 位元組資料的糾錯碼位元組 2

0x3A

ECC 位元組 18

此頁第七個 256 位元組資料的糾錯碼位元組 0

0x3B

ECC 位元組 19

此頁第七個 256 位元組資料的糾錯碼位元組 1

0x3C

ECC 位元組 20

此頁第七個 256 位元組資料的糾錯碼位元組 2

0x3D

ECC 位元組 21

此頁第八個 256 位元組資料的糾錯碼位元組 0

0x3E

ECC 位元組 22

此頁第八個 256 位元組資料的糾錯碼位元組 1

0x3F

ECC 位元組 23

此頁第八個 256 位元組資料的糾錯碼位元組 2

檔案系統支援

NAND 驅動程式透過 MTD 介面提供檔案系統所需的所有功能。

檔案系統必須瞭解 NAND 的特性和限制。 NAND 快閃記憶體的一個主要限制是,您不能像您希望的那樣頻繁地寫入頁面。在再次擦除頁面之前,對頁面的連續寫入限制為 1-3 次寫入,具體取決於製造商的規格。這同樣適用於備用區域。

因此,NAND 感知檔案系統必須以頁面大小的塊寫入,或者儲存一個寫緩衝區來收集較小的寫入,直到它們加起來達到頁面大小。可用的 NAND 感知檔案系統:JFFS2、YAFFS。

用於儲存檔案系統資料的備用區域使用由備用區域放置功能控制,該功能在前面的章節中進行了描述。

工具

MTD 專案提供了一些有用的工具來處理 NAND 快閃記憶體。

  • flasherase、flasheraseall:擦除和格式化 FLASH 分割槽

  • nandwrite:將檔案系統映像寫入 NAND FLASH

  • nanddump:轉儲 NAND FLASH 分割槽的內容

這些工具瞭解 NAND 的限制。請使用這些工具,而不是抱怨由非 NAND 感知訪問方法引起的錯誤。

常量

本章介紹可能與驅動程式開發人員相關的常量。

晶片選項常量

晶片 ID 表的常量

這些常量在 rawnand.h 中定義。它們被 OR 在一起以描述晶片功能

/* Buswitdh is 16 bit */
#define NAND_BUSWIDTH_16    0x00000002
/* Device supports partial programming without padding */
#define NAND_NO_PADDING     0x00000004
/* Chip has cache program function */
#define NAND_CACHEPRG       0x00000008
/* Chip has copy back function */
#define NAND_COPYBACK       0x00000010
/* AND Chip which has 4 banks and a confusing page / block
 * assignment. See Renesas datasheet for further information */
#define NAND_IS_AND     0x00000020
/* Chip has a array of 4 pages which can be read without
 * additional ready /busy waits */
#define NAND_4PAGE_ARRAY    0x00000040

執行時選項的常量

這些常量在 rawnand.h 中定義。它們被 OR 在一起以描述功能

/* The hw ecc generator provides a syndrome instead a ecc value on read
 * This can only work if we have the ecc bytes directly behind the
 * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
#define NAND_HWECC_SYNDROME 0x00020000

ECC 選擇常量

使用這些常量來選擇 ECC 演算法

/* No ECC. Usage is not recommended ! */
#define NAND_ECC_NONE       0
/* Software ECC 3 byte ECC per 256 Byte data */
#define NAND_ECC_SOFT       1
/* Hardware ECC 3 byte ECC per 256 Byte data */
#define NAND_ECC_HW3_256    2
/* Hardware ECC 3 byte ECC per 512 Byte data */
#define NAND_ECC_HW3_512    3
/* Hardware ECC 6 byte ECC per 512 Byte data */
#define NAND_ECC_HW6_512    4
/* Hardware ECC 8 byte ECC per 512 Byte data */
#define NAND_ECC_HW8_512    6

結構

本章包含 NAND 驅動程式中使用的結構並且可能與驅動程式開發人員相關的自動生成文件。每個結構成員都有一個簡短的描述,標記有 [XXX] 識別符號。有關說明,請參見“文件提示”一章。

struct nand_parameters

來自引數頁面的 NAND 通用引數

定義:

struct nand_parameters {
    const char *model;
    bool supports_set_get_features;
    bool supports_read_cache;
    unsigned long set_feature_list[BITS_TO_LONGS(ONFI_FEATURE_NUMBER)];
    unsigned long get_feature_list[BITS_TO_LONGS(ONFI_FEATURE_NUMBER)];
    struct onfi_params *onfi;
};

成員

model

型號名稱

supports_set_get_features

NAND 晶片支援設定/獲取特性

supports_read_cache

NAND 晶片支援讀取快取操作

set_feature_list

可以設定的特性的點陣圖

get_feature_list

可以獲取的特性的點陣圖

onfi

ONFI 特定引數

struct nand_id

NAND ID 結構

定義:

struct nand_id {
    u8 data[NAND_MAX_ID_LEN];
    int len;
};

成員

data

包含 ID 位元組的緩衝區。

len

ID 長度。

struct nand_ecc_step_info

ECC 引擎的 ECC 步資訊

定義:

struct nand_ecc_step_info {
    int stepsize;
    const int *strengths;
    int nstrengths;
};

成員

stepsize

每個 ECC 步的資料位元組數

strengths

支援的強度陣列

nstrengths

支援的強度數

struct nand_ecc_caps

ECC 引擎的功能

定義:

struct nand_ecc_caps {
    const struct nand_ecc_step_info *stepinfos;
    int nstepinfos;
    int (*calc_ecc_bytes)(int step_size, int strength);
};

成員

stepinfos

ECC 步資訊陣列

nstepinfos

ECC 步資訊數

calc_ecc_bytes

驅動程式的鉤子,用於計算每個步的 ECC 位元組數

struct nand_ecc_ctrl

ECC 的控制結構

定義:

struct nand_ecc_ctrl {
    enum nand_ecc_engine_type engine_type;
    enum nand_ecc_placement placement;
    enum nand_ecc_algo algo;
    int steps;
    int size;
    int bytes;
    int total;
    int strength;
    int prepad;
    int postpad;
    unsigned int options;
    u8 *calc_buf;
    u8 *code_buf;
    void (*hwctl)(struct nand_chip *chip, int mode);
    int (*calculate)(struct nand_chip *chip, const uint8_t *dat, uint8_t *ecc_code);
    int (*correct)(struct nand_chip *chip, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc);
    int (*read_page_raw)(struct nand_chip *chip, uint8_t *buf, int oob_required, int page);
    int (*write_page_raw)(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page);
    int (*read_page)(struct nand_chip *chip, uint8_t *buf, int oob_required, int page);
    int (*read_subpage)(struct nand_chip *chip, uint32_t offs, uint32_t len, uint8_t *buf, int page);
    int (*write_subpage)(struct nand_chip *chip, uint32_t offset,uint32_t data_len, const uint8_t *data_buf, int oob_required, int page);
    int (*write_page)(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page);
    int (*write_oob_raw)(struct nand_chip *chip, int page);
    int (*read_oob_raw)(struct nand_chip *chip, int page);
    int (*read_oob)(struct nand_chip *chip, int page);
    int (*write_oob)(struct nand_chip *chip, int page);
};

成員

engine_type

ECC 引擎型別

placement

OOB 位元組放置

algo

ECC 演算法

steps

每頁的 ECC 步數

size

每個 ECC 步的資料位元組數

位元組

每個步的 ECC 位元組數

total

每頁的 ECC 位元組總數

strength

每個 ECC 步可糾正的最大位數

prepad

基於綜合症的 ECC 生成器的填充資訊

postpad

基於綜合症的 ECC 生成器的填充資訊

options

ECC 特定選項(參見上面定義的 NAND_ECC_XXX 標誌)

calc_buf

用於計算 ECC 的緩衝區,大小為 oobsize。

code_buf

從快閃記憶體讀取的 ECC 緩衝區,大小為 oobsize。

hwctl

用於控制硬體 ECC 生成器的函式。僅當硬體 ECC 可用時才必須提供

calculate

用於 ECC 計算或從 ECC 硬體回讀的函式

correct

用於 ECC 校正的函式,與 ECC 生成器(sw/hw)匹配。如果位翻轉的數量超過 ECC 強度,則應返回表示已校正位翻轉數量的正數,-EBADMSG;如果錯誤與校正沒有直接關係,則返回任何其他錯誤程式碼。如果返回 -EBADMSG,則應保持輸入緩衝區不變。

read_page_raw

用於讀取沒有 ECC 的原始頁面的函式。此函式應隱藏 ECC 控制器使用的特定佈局,並始終返回連續的帶內和帶外資料,即使它們沒有連續儲存在 NAND 晶片上(例如,NAND_ECC_PLACEMENT_INTERLEAVED 交錯帶內和帶外資料)。

write_page_raw

用於寫入沒有 ECC 的原始頁面的函式。此函式應隱藏 ECC 控制器使用的特定佈局,並將傳遞的資料視為連續的帶內和帶外資料。ECC 控制器負責進行適當的轉換以適應其特定佈局(例如,NAND_ECC_PLACEMENT_INTERLEAVED 交錯帶內和帶外資料)。

read_page

用於根據 ECC 生成器要求讀取頁面的函式;返回任何單個 ECC 步中校正的最大位翻轉數,-EIO hw 錯誤

read_subpage

用於讀取 ECC 覆蓋的頁面的部分的函式;返回與 read_page() 相同

write_subpage

用於寫入 ECC 覆蓋的頁面的部分的函式。

write_page

用於根據 ECC 生成器要求寫入頁面的函式。

write_oob_raw

用於寫入沒有 ECC 的晶片 OOB 資料的函式

read_oob_raw

用於讀取沒有 ECC 的晶片 OOB 資料的函式

read_oob

用於讀取晶片 OOB 資料的函式

write_oob

用於寫入晶片 OOB 資料的函式

struct nand_sdr_timings

SDR NAND 晶片時序

定義:

struct nand_sdr_timings {
    u64 tBERS_max;
    u32 tCCS_min;
    u64 tPROG_max;
    u64 tR_max;
    u32 tALH_min;
    u32 tADL_min;
    u32 tALS_min;
    u32 tAR_min;
    u32 tCEA_max;
    u32 tCEH_min;
    u32 tCH_min;
    u32 tCHZ_max;
    u32 tCLH_min;
    u32 tCLR_min;
    u32 tCLS_min;
    u32 tCOH_min;
    u32 tCS_min;
    u32 tDH_min;
    u32 tDS_min;
    u32 tFEAT_max;
    u32 tIR_min;
    u32 tITC_max;
    u32 tRC_min;
    u32 tREA_max;
    u32 tREH_min;
    u32 tRHOH_min;
    u32 tRHW_min;
    u32 tRHZ_max;
    u32 tRLOH_min;
    u32 tRP_min;
    u32 tRR_min;
    u64 tRST_max;
    u32 tWB_max;
    u32 tWC_min;
    u32 tWH_min;
    u32 tWHR_min;
    u32 tWP_min;
    u32 tWW_min;
};

成員

tBERS_max

塊擦除時間

tCCS_min

更改列設定時間

tPROG_max

頁面程式設計時間

tR_max

頁面讀取時間

tALH_min

ALE 保持時間

tADL_min

ALE 到資料載入時間

tALS_min

ALE 設定時間

tAR_min

ALE 到 RE# 延遲

tCEA_max

CE# 訪問時間

tCEH_min

CE# 高電平保持時間

tCH_min

CE# 保持時間

tCHZ_max

CE# 高電平到輸出高阻抗

tCLH_min

CLE 保持時間

tCLR_min

CLE 到 RE# 延遲

tCLS_min

CLE 設定時間

tCOH_min

CE# 高電平到輸出保持

tCS_min

CE# 設定時間

tDH_min

資料保持時間

tDS_min

資料設定時間

tFEAT_max

設定特性和獲取特性的繁忙時間

tIR_min

輸出高阻抗到 RE# 低電平

tITC_max

介面和時序模式更改時間

tRC_min

RE# 週期時間

tREA_max

RE# 訪問時間

tREH_min

RE# 高電平保持時間

tRHOH_min

RE# 高電平到輸出保持

tRHW_min

RE# 高電平到 WE# 低電平

tRHZ_max

RE# 高電平到輸出高阻抗

tRLOH_min

RE# 低電平到輸出保持

tRP_min

RE# 脈衝寬度

tRR_min

就緒到 RE# 低電平(僅限資料)

tRST_max

裝置重置時間,從 R/B# 的下降沿到 R/B# 的上升沿測量。

tWB_max

WE# 高電平到 SR[6] 低電平

tWC_min

WE# 週期時間

tWH_min

WE# 高電平保持時間

tWHR_min

WE# 高電平到 RE# 低電平

tWP_min

WE# 脈衝寬度

tWW_min

WP# 轉換到 WE# 低電平

描述

此結構定義了 SDR NAND 晶片的時序要求。這些資訊可以在每個 NAND 資料表中找到,並且時序含義在 ONFI 規範中描述:https://media-www.micron.com/-/media/client/onfi/specs/onfi_3_1_spec.pdf(第 4.15 章時序引數)

所有這些時序都以皮秒錶示。

struct nand_nvddr_timings

NV-DDR NAND 晶片時序

定義:

struct nand_nvddr_timings {
    u64 tBERS_max;
    u32 tCCS_min;
    u64 tPROG_max;
    u64 tR_max;
    u32 tAC_min;
    u32 tAC_max;
    u32 tADL_min;
    u32 tCAD_min;
    u32 tCAH_min;
    u32 tCALH_min;
    u32 tCALS_min;
    u32 tCAS_min;
    u32 tCEH_min;
    u32 tCH_min;
    u32 tCK_min;
    u32 tCS_min;
    u32 tDH_min;
    u32 tDQSCK_min;
    u32 tDQSCK_max;
    u32 tDQSD_min;
    u32 tDQSD_max;
    u32 tDQSHZ_max;
    u32 tDQSQ_max;
    u32 tDS_min;
    u32 tDSC_min;
    u32 tFEAT_max;
    u32 tITC_max;
    u32 tQHS_max;
    u32 tRHW_min;
    u32 tRR_min;
    u32 tRST_max;
    u32 tWB_max;
    u32 tWHR_min;
    u32 tWRCK_min;
    u32 tWW_min;
};

成員

tBERS_max

塊擦除時間

tCCS_min

更改列設定時間

tPROG_max

頁面程式設計時間

tR_max

頁面讀取時間

tAC_min

DQ[7:0] 從 CLK 的訪問視窗

tAC_max

DQ[7:0] 從 CLK 的訪問視窗

tADL_min

ALE 到資料載入時間

tCAD_min

命令、地址、資料延遲

tCAH_min

命令/地址 DQ 保持時間

tCALH_min

W/R_n、CLE 和 ALE 保持時間

tCALS_min

W/R_n、CLE 和 ALE 設定時間

tCAS_min

命令/地址 DQ 設定時間

tCEH_min

CE# 高電平保持時間

tCH_min

CE# 保持時間

tCK_min

平均時鐘週期時間

tCS_min

CE# 設定時間

tDH_min

資料保持時間

tDQSCK_min

DQS 從 CLK 的訪問視窗的開始

tDQSCK_max

DQS 從 CLK 的訪問視窗的結束

tDQSD_min

最小 W/R_n 低電平到 DQS/DQ 由裝置驅動

tDQSD_max

最大 W/R_n 低電平到 DQS/DQ 由裝置驅動

tDQSHZ_max

W/R_n 高電平到 DQS/DQ 由裝置三態

tDQSQ_max

DQS-DQ 傾斜,DQS 到最後一個 DQ 有效,每次訪問

tDS_min

資料設定時間

tDSC_min

DQS 週期時間

tFEAT_max

設定特性和獲取特性的繁忙時間

tITC_max

介面和時序模式更改時間

tQHS_max

資料保持傾斜因子

tRHW_min

資料輸出週期到命令、地址或資料輸入週期

tRR_min

就緒到 RE# 低電平(僅限資料)

tRST_max

裝置重置時間,從 R/B# 的下降沿到 R/B# 的上升沿測量。

tWB_max

WE# 高電平到 SR[6] 低電平

tWHR_min

WE# 高電平到 RE# 低電平

tWRCK_min

W/R_n 低電平到資料輸出週期

tWW_min

WP# 轉換到 WE# 低電平

描述

此結構定義了 NV-DDR NAND 資料介面的時序要求。這些資訊可以在每個 NAND 資料表中找到,並且時序含義在 ONFI 規範中描述:https://media-www.micron.com/-/media/client/onfi/specs/onfi_4_1_gold.pdf(第 4.18.2 章 NV-DDR)

所有這些時序都以皮秒錶示。

enum nand_interface_type

NAND 介面型別

常量

NAND_SDR_IFACE

單資料速率介面

NAND_NVDDR_IFACE

雙資料速率介面

struct nand_interface_config

NAND 介面時序

定義:

struct nand_interface_config {
    enum nand_interface_type type;
    struct nand_timings {
        unsigned int mode;
        union {
            struct nand_sdr_timings sdr;
            struct nand_nvddr_timings nvddr;
        };
    } timings;
};

成員

type

時序型別

timings

時序資訊

timings.mode

規範中定義的時序模式

{unnamed_union}

anonymous

timings.sdr

typeNAND_SDR_IFACE 時使用它。

timings.nvddr

typeNAND_NVDDR_IFACE 時使用它。

bool nand_interface_is_sdr(const struct nand_interface_config *conf)

獲取介面型別

引數

const struct nand_interface_config *conf

資料介面

bool nand_interface_is_nvddr(const struct nand_interface_config *conf)

獲取介面型別

引數

const struct nand_interface_config *conf

資料介面

const struct nand_sdr_timings *nand_get_sdr_timings(const struct nand_interface_config *conf)

從資料介面獲取 SDR 時序

引數

const struct nand_interface_config *conf

資料介面

const struct nand_nvddr_timings *nand_get_nvddr_timings(const struct nand_interface_config *conf)

從資料介面獲取 NV-DDR 時序

引數

const struct nand_interface_config *conf

資料介面

struct nand_op_cmd_instr

命令指令的定義

定義:

struct nand_op_cmd_instr {
    u8 opcode;
};

成員

opcode

在一個週期內發出的命令

struct nand_op_addr_instr

地址指令的定義

定義:

struct nand_op_addr_instr {
    unsigned int naddrs;
    const u8 *addrs;
};

成員

naddrs

addrs 陣列的長度

addrs

包含要發出的地址週期的陣列

struct nand_op_data_instr

資料指令的定義

定義:

struct nand_op_data_instr {
    unsigned int len;
    union {
        void *in;
        const void *out;
    } buf;
    bool force_8bit;
};

成員

len

要移動的資料位元組數

buf

要填充的緩衝區

buf.in

從 NAND 晶片讀取時要填充的緩衝區

buf.out

寫入 NAND 晶片時要讀取的緩衝區

force_8bit

強制 8 位訪問

描述

請注意,“in”和“out”與 ONFI 規範相反,並且是從控制器的角度來看的,因此“in”是從 NAND 晶片讀取,而“out”是寫入 NAND 晶片。

struct nand_op_waitrdy_instr

等待就緒指令的定義

定義:

struct nand_op_waitrdy_instr {
    unsigned int timeout_ms;
};

成員

timeout_ms

等待就緒/忙碌引腳的最長延遲時間,單位為毫秒

enum nand_op_instr_type

所有指令型別的定義

常量

NAND_OP_CMD_INSTR

命令指令

NAND_OP_ADDR_INSTR

地址指令

NAND_OP_DATA_IN_INSTR

資料輸入指令

NAND_OP_DATA_OUT_INSTR

資料輸出指令

NAND_OP_WAITRDY_INSTR

等待就緒指令

struct nand_op_instr

指令物件

定義:

struct nand_op_instr {
    enum nand_op_instr_type type;
    union {
        struct nand_op_cmd_instr cmd;
        struct nand_op_addr_instr addr;
        struct nand_op_data_instr data;
        struct nand_op_waitrdy_instr waitrdy;
    } ctx;
    unsigned int delay_ns;
};

成員

type

指令型別

ctx

與指令關聯的額外資料。您必須使用取決於 type 的適當元素

ctx.cmd

如果 typeNAND_OP_CMD_INSTR,則使用它

ctx.addr

如果 typeNAND_OP_ADDR_INSTR,則使用它

ctx.data

如果 typeNAND_OP_DATA_IN_INSTRNAND_OP_DATA_OUT_INSTR,則使用它

ctx.waitrdy

如果 typeNAND_OP_WAITRDY_INSTR,則使用它

delay_ns

控制器在總線上發出指令後應應用的延遲。大多數現代控制器都具有內部時序控制邏輯,在這種情況下,控制器驅動程式可以忽略此欄位。

struct nand_subop

子操作

定義:

struct nand_subop {
    unsigned int cs;
    const struct nand_op_instr *instrs;
    unsigned int ninstrs;
    unsigned int first_instr_start_off;
    unsigned int last_instr_end_off;
};

成員

cs

要為此 NAND 子操作選擇的 CS 線

instrs

指令陣列

ninstrs

instrs 陣列的長度

first_instr_start_off

子操作的第一個指令的起始偏移量

last_instr_end_off

子操作的最後一個指令的結束偏移量(不包括)

描述

first_instr_start_offlast_instr_end_off 都僅適用於資料或地址指令。

當 NAND 控制器無法按原樣處理操作時,解析器會將其拆分為子操作,這些子操作將傳遞給控制器驅動程式。

struct nand_op_parser_addr_constraints

地址指令的約束

定義:

struct nand_op_parser_addr_constraints {
    unsigned int maxcycles;
};

成員

maxcycles

控制器在單個步驟中可以發出的最大地址週期數

struct nand_op_parser_data_constraints

資料指令的約束

定義:

struct nand_op_parser_data_constraints {
    unsigned int maxlen;
};

成員

maxlen

控制器在單個步驟中可以處理的最大資料長度

struct nand_op_parser_pattern_elem

模式的一個元素

定義:

struct nand_op_parser_pattern_elem {
    enum nand_op_instr_type type;
    bool optional;
    union {
        struct nand_op_parser_addr_constraints addr;
        struct nand_op_parser_data_constraints data;
    } ctx;
};

成員

type

指令型別

optional

模式的這個元素是可選的還是強制的

ctx

地址或資料約束

ctx.addr

地址約束(週期數)

ctx.data

資料約束(資料長度)

struct nand_op_parser_pattern

NAND 子操作模式描述符

定義:

struct nand_op_parser_pattern {
    const struct nand_op_parser_pattern_elem *elems;
    unsigned int nelems;
    int (*exec)(struct nand_chip *chip, const struct nand_subop *subop);
};

成員

elems

模式元素陣列

nelems

elems 陣列中模式元素的數量

exec

將發出子操作的函式

描述

模式是元素的列表,每個元素代表一個帶有其約束的指令。核心使用該模式本身將 NAND 晶片操作與 NAND 控制器操作進行匹配。一旦找到 NAND 控制器操作模式與 NAND 晶片操作(或 NAND 操作的子集)之間的匹配,就會呼叫 pattern ->exec() 鉤子,以便控制器驅動程式可以在總線上發出該操作。

控制器驅動程式應宣告儘可能多的它們支援的模式,並將此模式列表(藉助以下宏建立)傳遞給 nand_op_parser_exec_op() 輔助函式。

struct nand_op_parser

NAND 控制器操作解析器描述符

定義:

struct nand_op_parser {
    const struct nand_op_parser_pattern *patterns;
    unsigned int npatterns;
};

成員

patterns

支援的模式陣列

npatterns

patterns 陣列的長度

描述

解析器描述符只是一個支援的模式陣列,每次 nand_op_parser_exec_op() 嘗試執行 NAND 操作(或嘗試確定是否支援特定操作)時,它都會迭代該陣列。

值得一提的是,將按照宣告順序測試模式,並且將採用第一個匹配項,因此重要的是適當排序模式,以便將簡單/低效的模式放在列表的末尾。通常,這是放置單指令模式的地方。

struct nand_operation

NAND 操作描述符

定義:

struct nand_operation {
    unsigned int cs;
    bool deassert_wp;
    const struct nand_op_instr *instrs;
    unsigned int ninstrs;
};

成員

cs

要為此 NAND 操作選擇的 CS 線

deassert_wp

當操作需要取消斷言 WP 引腳時設定為 true(ERASE、PROG 等)

instrs

要執行的指令陣列

ninstrs

instrs 陣列的長度

描述

將傳遞給 chip->exec_op() 的實際操作結構。

struct nand_controller_ops

控制器操作

定義:

struct nand_controller_ops {
    int (*attach_chip)(struct nand_chip *chip);
    void (*detach_chip)(struct nand_chip *chip);
    int (*exec_op)(struct nand_chip *chip,const struct nand_operation *op, bool check_only);
    int (*setup_interface)(struct nand_chip *chip, int chipnr, const struct nand_interface_config *conf);
};

成員

attach_chip

在快閃記憶體 ID 和 MTD 欄位(例如擦除大小、頁面大小和 OOB 大小)設定完畢後,在 NAND 檢測階段之後呼叫此方法。如果 NAND 晶片或裝置樹提供,則 ECC 要求可用。通常用於選擇適當的 ECC 配置並分配關聯的資源。此鉤子是可選的。

detach_chip

釋放 nand_controller_ops->attach_chip() 中分配/宣告的所有資源。此鉤子是可選的。

exec_op

執行 NAND 操作的控制器特定方法。此方法替換 chip->legacy.cmdfunc()、chip->legacy.{read,write}_{buf,byte,word}()、chip->legacy.dev_ready() 和 chip->legacy.waitfunc()。

setup_interface

設定資料介面和時序。如果 chipnr 設定為 NAND_DATA_IFACE_CHECK_ONLY,則表示不應應用配置,而僅應檢查配置。此鉤子是可選的。

struct nand_controller

用於描述 NAND 控制器的結構

定義:

struct nand_controller {
    struct mutex lock;
    const struct nand_controller_ops *ops;
    struct {
        unsigned int data_only_read: 1;
        unsigned int cont_read: 1;
    } supported_op;
    bool controller_wp;
};

成員

lock

用於序列化對 NAND 控制器的訪問的鎖

ops

NAND 控制器操作。

supported_op

NAND 控制器已知支援的操作,僅在初始檢查後可由核心寫入。

supported_op.data_only_read

控制器支援從匯流排讀取更多資料,而無需重新啟動整個讀取操作或更改列。

supported_op.cont_read

控制器支援順序快取讀取。

controller_wp

控制器負責處理 WP 引腳。

struct nand_legacy

NAND 晶片傳統欄位/鉤子

定義:

struct nand_legacy {
    void __iomem *IO_ADDR_R;
    void __iomem *IO_ADDR_W;
    void (*select_chip)(struct nand_chip *chip, int cs);
    u8 (*read_byte)(struct nand_chip *chip);
    void (*write_byte)(struct nand_chip *chip, u8 byte);
    void (*write_buf)(struct nand_chip *chip, const u8 *buf, int len);
    void (*read_buf)(struct nand_chip *chip, u8 *buf, int len);
    void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl);
    void (*cmdfunc)(struct nand_chip *chip, unsigned command, int column, int page_addr);
    int (*dev_ready)(struct nand_chip *chip);
    int (*waitfunc)(struct nand_chip *chip);
    int (*block_bad)(struct nand_chip *chip, loff_t ofs);
    int (*block_markbad)(struct nand_chip *chip, loff_t ofs);
    int (*set_features)(struct nand_chip *chip, int feature_addr, u8 *subfeature_para);
    int (*get_features)(struct nand_chip *chip, int feature_addr, u8 *subfeature_para);
    int chip_delay;
    struct nand_controller dummy_controller;
};

成員

IO_ADDR_R

讀取快閃記憶體裝置的 8 條 I/O 線的地址

IO_ADDR_W

寫入快閃記憶體裝置的 8 條 I/O 線的地址

select_chip

選擇/取消選擇特定的目標/裸片

read_byte

從晶片讀取一個位元組

write_byte

在低 8 條 I/O 線上向晶片寫入單個位元組

write_buf

將資料從緩衝區寫入晶片

read_buf

將資料從晶片讀取到緩衝區

cmd_ctrl

用於控制 ALE/CLE/nCE 的硬體特定函式。也用於寫入命令和地址

cmdfunc

用於將命令寫入晶片的硬體特定函式。

dev_ready

用於訪問裝置就緒/忙碌線的硬體特定函式。如果設定為 NULL,則無法訪問就緒/忙碌,並且就緒/忙碌資訊從晶片狀態暫存器讀取。

waitfunc

用於等待就緒的硬體特定函式。

block_bad

使用 OOB 標記檢查塊是否損壞

block_markbad

將塊標記為壞塊

set_features

設定 NAND 晶片特性

get_features

獲取 NAND 晶片特性

chip_delay

晶片相關的延遲,用於將資料從陣列傳輸到讀取暫存器 (tR)。

dummy_controller

僅可控制單個晶片的驅動程式的虛擬控制器實現

描述

如果您檢視此結構,您已經錯了。這些欄位/鉤子都已棄用。

struct nand_chip_ops

NAND 晶片操作

定義:

struct nand_chip_ops {
    int (*suspend)(struct nand_chip *chip);
    void (*resume)(struct nand_chip *chip);
    int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
    int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
    int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
    int (*choose_interface_config)(struct nand_chip *chip, struct nand_interface_config *iface);
};

成員

suspend

掛起操作

resume

恢復操作

lock_area

鎖定操作

unlock_area

解鎖操作

setup_read_retry

設定讀取重試模式(主要用於 MLC NAND)

choose_interface_config

選擇最佳介面配置

struct nand_manufacturer

NAND 製造商結構

定義:

struct nand_manufacturer {
    const struct nand_manufacturer_desc *desc;
    void *priv;
};

成員

desc

製造商描述

priv

製造商驅動程式的私有資訊

struct nand_secure_region

NAND 安全區域結構

定義:

struct nand_secure_region {
    u64 offset;
    u64 size;
};

成員

offset

安全區域起點的偏移量

size

安全區域的大小

struct nand_chip

NAND 私有快閃記憶體晶片資料

定義:

struct nand_chip {
    struct nand_device base;
    struct nand_id id;
    struct nand_parameters parameters;
    struct nand_manufacturer manufacturer;
    struct nand_chip_ops ops;
    struct nand_legacy legacy;
    unsigned int options;
    const struct nand_interface_config *current_interface_config;
    struct nand_interface_config *best_interface_config;
    unsigned int bbt_erase_shift;
    unsigned int bbt_options;
    unsigned int badblockpos;
    unsigned int badblockbits;
    struct nand_bbt_descr *bbt_td;
    struct nand_bbt_descr *bbt_md;
    struct nand_bbt_descr *badblock_pattern;
    u8 *bbt;
    unsigned int page_shift;
    unsigned int phys_erase_shift;
    unsigned int chip_shift;
    unsigned int pagemask;
    unsigned int subpagesize;
    u8 *data_buf;
    u8 *oob_poi;
    struct {
        unsigned int bitflips;
        int page;
    } pagecache;
    unsigned long buf_align;
    struct mutex lock;
    unsigned int suspended : 1;
    wait_queue_head_t resume_wq;
    int cur_cs;
    int read_retries;
    struct nand_secure_region *secure_regions;
    u8 nr_secure_regions;
    struct {
        bool ongoing;
        unsigned int first_page;
        unsigned int pause_page;
        unsigned int last_page;
    } cont_read;
    struct nand_controller *controller;
    struct nand_ecc_ctrl ecc;
    void *priv;
};

成員

base

從通用 NAND 裝置繼承

id

儲存 NAND ID

parameters

以易於閱讀的形式儲存通用引數

manufacturer

製造商資訊

ops

NAND 晶片操作

legacy

所有傳統欄位/鉤子。如果您開發新的驅動程式,請甚至不要嘗試使用這些欄位/鉤子中的任何一個,並且如果您正在修改使用這些欄位/鉤子的現有驅動程式,則應考慮重新設計驅動程式並避免使用它們。

options

各種晶片選項。它們可以部分設定為通知 nand_scan 特殊功能。有關進一步說明,請參見定義。

current_interface_config

當前使用的 NAND 介面配置

best_interface_config

最適合 NAND 晶片和 NAND 控制器約束的最佳 NAND 介面配置。如果未設定,則必須使用預設的重置介面配置。

bbt_erase_shift

bbt 條目中的地址位數

bbt_options

壞塊表特定選項。此處使用的所有選項都必須來自 bbm.h。預設情況下,這些選項將複製到適當的 nand_bbt_descr 中。

badblockpos

oob 區域中的壞塊標記位置

badblockbits

好塊的壞塊標記位置中的最小設定位數;即,當 badblockbits = 7 時,BBM = 11110111b 是好塊

bbt_td

用於快閃記憶體查詢的壞塊表描述符

bbt_md

壞塊表映象描述符

badblock_pattern

用於初始壞塊掃描的壞塊掃描模式

bbt

壞塊表指標

page_shift

頁面中的地址位數(列地址位數)

phys_erase_shift

物理擦除塊中的地址位數

chip_shift

一個晶片中的地址位數

pagemask

頁面號掩碼 = (頁面數 / 晶片數) - 1

subpagesize

儲存子頁面大小

data_buf

用於資料的緩衝區,大小為 (頁面大小 + oobsize)

oob_poi

data_buf 覆蓋的 OOB 區域上的指標

pagecache

包含頁面快取相關欄位的結構

pagecache.bitflips

快取頁面的位翻轉數

pagecache.page

當前在快取中的頁面號。-1 表示當前未快取任何頁面

buf_align

平臺所需的最小緩衝區對齊

lock

保護掛起欄位的鎖。也用於序列化對 NAND 裝置的訪問

suspended

當裝置掛起時設定為 1,未掛起時設定為 0

resume_wq

如果 rawnand 處於掛起狀態,則等待睡眠的佇列。

cur_cs

當前選定的目標。-1 表示未選擇任何目標,否則我們應始終具有 cur_cs >= 0 && cur_cs < nanddev_ntargets()。NAND 控制器驅動程式不應修改此值,但允許讀取該值。

read_retries

支援的讀取重試模式的數量

secure_regions

包含安全區域資訊的結構

nr_secure_regions

安全區域的數量

cont_read

順序頁面讀取內部

cont_read.ongoing

是否正在進行連續讀取

cont_read.first_page

連續讀取操作的開始

cont_read.pause_page

當前順序快取讀取操作的結束

cont_read.last_page

連續讀取操作的結束

controller

在多個獨立裝置之間共享的硬體控制器結構

ecc

ECC 控制器結構

priv

晶片私有資料

const struct nand_interface_config *nand_get_interface_config(struct nand_chip *chip)

獲取 NAND 晶片的當前介面配置

引數

struct nand_chip *chip

NAND 晶片

struct nand_flash_dev

NAND Flash 裝置 ID 結構體

定義:

struct nand_flash_dev {
    char *name;
    union {
        struct {
            uint8_t mfr_id;
            uint8_t dev_id;
        };
        uint8_t id[NAND_MAX_ID_LEN];
    };
    unsigned int pagesize;
    unsigned int chipsize;
    unsigned int erasesize;
    unsigned int options;
    uint16_t id_len;
    uint16_t oobsize;
    struct {
        uint16_t strength_ds;
        uint16_t step_ds;
    } ecc;
};

成員

name

NAND 晶片的可讀名稱

{unnamed_union}

anonymous

{unnamed_struct}

anonymous

mfr_id

完整晶片 ID 陣列的製造商 ID 部分 (指向與 id[0] 相同的記憶體地址)

dev_id

完整晶片 ID 陣列的裝置 ID 部分 (指向與 id[1] 相同的記憶體地址)

id

完整裝置 ID 陣列

pagesize

NAND 頁的大小,單位為位元組;如果為 0,則實際頁大小(以及擦除塊大小)將從擴充套件 NAND 晶片 ID 陣列中確定

chipsize

總晶片大小,單位為 MiB

erasesize

擦除塊大小,單位為位元組 (如果為 0,則從擴充套件 ID 確定)

options

儲存各種晶片位選項

id_len

id 的有效長度。

oobsize

OOB 大小

ecc

來自資料手冊的 ECC 糾錯能力和步長資訊。

ecc.strength_ds

來自資料手冊的 ECC 糾錯能力,與 nand_chip{} 中的 ecc_strength_ds 相同。

ecc.step_ds

ecc.strength_ds 所需的 ECC 步長,與 nand_chip{} 中的 ecc_step_ds 相同,也來自資料手冊。例如,“每個 512Byte 的 4bit ECC”可以使用 NAND_ECC_INFO(4, 512) 設定。

int nand_opcode_8bits(unsigned int command)

檢查操作碼的地址是否僅應在低 8 位上傳送

引數

unsigned int command

要檢查的操作碼

void *nand_get_data_buf(struct nand_chip *chip)

獲取內部頁面緩衝區

引數

struct nand_chip *chip

NAND 晶片物件

描述

返回使快取無效後的預分配頁面緩衝區。驅動程式不希望分配自己的反彈緩衝區,但仍然需要用於特定操作(最常見的是僅讀取 OOB 資料)的緩衝區時,應使用此函式。

小心不要在寫入/write_oob 路徑中呼叫此函式,因為核心可能已將要寫入的資料放置在此緩衝區中。

返回

指向頁面快取緩衝區的指標

提供的公共函式

本章包含匯出的 NAND 核心 API 函式的自動生成文件。每個函式都有一個簡短的描述,標記有 [XXX] 識別符號。有關說明,請參見“文件提示”一章。

void nand_extract_bits(u8 *dst, unsigned int dst_off, const u8 *src, unsigned int src_off, unsigned int nbits)

將未對齊的位從一個緩衝區複製到另一個緩衝區

引數

u8 *dst

目標緩衝區

unsigned int dst_off

寫入開始的位偏移量

const u8 *src

源緩衝區

unsigned int src_off

讀取開始的位偏移量

unsigned int nbits

要從 src 複製到 dst 的位數

描述

將位從一個記憶體區域複製到另一個記憶體區域(允許重疊)。

void nand_select_target(struct nand_chip *chip, unsigned int cs)

選擇一個 NAND 目標(又名 die)

引數

struct nand_chip *chip

NAND 晶片物件

unsigned int cs

要選擇的 CS 線。請注意,此 CS id 始終來自晶片 PoV,而不是控制器 PoV

描述

選擇一個 NAND 目標,以便在 chip 上執行的進一步操作將轉到所選的 NAND 目標。

void nand_deselect_target(struct nand_chip *chip)

取消選擇當前選擇的目標

引數

struct nand_chip *chip

NAND 晶片物件

描述

取消選擇當前選擇的 NAND 目標。取消選擇目標後,在 chip 上執行的操作的結果未定義。

int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)

輪詢 STATUS 暫存器,直到 RDY 位設定為 1

引數

struct nand_chip *chip

NAND 晶片結構體

unsigned long timeout_ms

超時時間,單位為毫秒

描述

使用 ->exec_op() 輪詢 STATUS 暫存器,直到 RDY 位變為 1。如果在指定的超時時間內未發生這種情況,則返回 -ETIMEDOUT。

當控制器無法訪問 NAND R/B 引腳時,應使用此輔助函式。

請注意,從 ->exec_op() 實現中呼叫此輔助函式意味著 ->exec_op() 必須是可重入的。

如果 NAND 晶片已準備就緒,則返回 0,否則返回負錯誤。

int nand_gpio_waitrdy(struct nand_chip *chip, struct gpio_desc *gpiod, unsigned long timeout_ms)

輪詢 R/B GPIO 引腳直到就緒

引數

struct nand_chip *chip

NAND 晶片結構體

struct gpio_desc *gpiod

R/B 引腳的 GPIO 描述符

unsigned long timeout_ms

超時時間,單位為毫秒

描述

輪詢 R/B GPIO 引腳,直到它變為就緒。如果在指定的超時時間內未發生這種情況,則返回 -ETIMEDOUT。

當控制器可以透過 GPIO 訪問 NAND R/B 引腳時,應使用此輔助函式。

如果 R/B 引腳指示晶片已準備好,則返回 0,否則返回負錯誤。

int nand_read_page_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, void *buf, unsigned int len)

執行 READ PAGE 操作

引數

struct nand_chip *chip

NAND 晶片

unsigned int page

要讀取的頁

unsigned int offset_in_page

頁面內的偏移量

void *buf

用於儲存資料的緩衝區

unsigned int len

緩衝區長度

描述

此函式發出 READ PAGE 操作。此函式不會選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_change_read_column_op(struct nand_chip *chip, unsigned int offset_in_page, void *buf, unsigned int len, bool force_8bit)

執行 CHANGE READ COLUMN 操作

引數

struct nand_chip *chip

NAND 晶片

unsigned int offset_in_page

頁面內的偏移量

void *buf

用於儲存資料的緩衝區

unsigned int len

緩衝區長度

bool force_8bit

強制 8 位匯流排訪問

描述

此函式發出 CHANGE READ COLUMN 操作。此函式不會選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_read_oob_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_oob, void *buf, unsigned int len)

執行 READ OOB 操作

引數

struct nand_chip *chip

NAND 晶片

unsigned int page

要讀取的頁

unsigned int offset_in_oob

OOB 區域內的偏移量

void *buf

用於儲存資料的緩衝區

unsigned int len

緩衝區長度

描述

此函式發出 READ OOB 操作。此函式不會選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, const void *buf, unsigned int len)

開始 PROG PAGE 操作

引數

struct nand_chip *chip

NAND 晶片

unsigned int page

要寫入的頁

unsigned int offset_in_page

頁面內的偏移量

const void *buf

包含要寫入頁面的資料的緩衝區

unsigned int len

緩衝區長度

描述

此函式發出 PROG PAGE 操作的前半部分。此函式不會選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_prog_page_end_op(struct nand_chip *chip)

結束 PROG PAGE 操作

引數

struct nand_chip *chip

NAND 晶片

描述

此函式發出 PROG PAGE 操作的後半部分。此函式不會選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_prog_page_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, const void *buf, unsigned int len)

執行完整的 PROG PAGE 操作

引數

struct nand_chip *chip

NAND 晶片

unsigned int page

要寫入的頁

unsigned int offset_in_page

頁面內的偏移量

const void *buf

包含要寫入頁面的資料的緩衝區

unsigned int len

緩衝區長度

描述

此函式發出完整的 PROG PAGE 操作。此函式不會選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_change_write_column_op(struct nand_chip *chip, unsigned int offset_in_page, const void *buf, unsigned int len, bool force_8bit)

執行 CHANGE WRITE COLUMN 操作

引數

struct nand_chip *chip

NAND 晶片

unsigned int offset_in_page

頁面內的偏移量

const void *buf

包含要傳送到 NAND 的資料的緩衝區

unsigned int len

緩衝區長度

bool force_8bit

強制 8 位匯流排訪問

描述

此函式發出 CHANGE WRITE COLUMN 操作。此函式不會選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, unsigned int len)

執行 READID 操作

引數

struct nand_chip *chip

NAND 晶片

u8 addr

在READID命令之後要經過的地址週期數

void *buf

用於儲存ID的緩衝區

unsigned int len

緩衝區長度

描述

此函式傳送READID命令並讀取NAND返回的ID。此函式不選擇/取消選擇CS線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_status_op(struct nand_chip *chip, u8 *status)

執行STATUS操作

引數

struct nand_chip *chip

NAND 晶片

u8 *status

用於儲存NAND狀態的輸出變數

描述

此函式傳送STATUS命令並讀取NAND返回的狀態。此函式不選擇/取消選擇CS線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_exit_status_op(struct nand_chip *chip)

退出STATUS操作

引數

struct nand_chip *chip

NAND 晶片

描述

此函式傳送READ0命令以取消STATUS命令的效果,以避免僅讀取狀態,直到傳送新的讀取命令。

此函式不選擇/取消選擇CS線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)

執行擦除操作

引數

struct nand_chip *chip

NAND 晶片

unsigned int eraseblock

要擦除的塊

描述

此函式傳送ERASE命令並等待NAND準備就緒後返回。此函式不選擇/取消選擇CS線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_reset_op(struct nand_chip *chip)

執行重置操作

引數

struct nand_chip *chip

NAND 晶片

描述

此函式傳送RESET命令並等待NAND準備就緒後返回。此函式不選擇/取消選擇CS線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, bool force_8bit, bool check_only)

從NAND讀取資料

引數

struct nand_chip *chip

NAND 晶片

void *buf

用於儲存資料的緩衝區

unsigned int len

緩衝區長度

bool force_8bit

強制 8 位匯流排訪問

bool check_only

不實際執行命令,僅檢查控制器驅動程式是否支援它

描述

此函式在總線上執行原始資料讀取。通常在啟動另一個NAND操作(如nand_read_page_op())之後使用。此函式不選擇/取消選擇CS線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_write_data_op(struct nand_chip *chip, const void *buf, unsigned int len, bool force_8bit)

從NAND寫入資料

引數

struct nand_chip *chip

NAND 晶片

const void *buf

包含要在總線上傳送的資料的緩衝區

unsigned int len

緩衝區長度

bool force_8bit

強制 8 位匯流排訪問

描述

此函式在總線上執行原始資料寫入。通常在啟動另一個NAND操作(如nand_write_page_begin_op())之後使用。此函式不選擇/取消選擇CS線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_op_parser_exec_op(struct nand_chip *chip, const struct nand_op_parser *parser, const struct nand_operation *op, bool check_only)

exec_op 解析器

引數

struct nand_chip *chip

NAND晶片

const struct nand_op_parser *parser

控制器驅動程式提供的模式描述

const struct nand_operation *op

要定址的NAND操作

bool check_only

如果為true,則該函式僅檢查是否可以處理 op,但不執行操作

描述

輔助函式,旨在簡化僅支援有限指令序列的NAND控制器驅動程式的整合。支援的序列在 parser 中描述,如果 check_only 設定為false,則框架負責將 op 分割為多個子操作,並將它們傳遞迴匹配模式的 ->exec() 回撥。

NAND控制器驅動程式應從其自身的 ->exec_op() 實現中呼叫此函式。

成功時返回0,否則返回負錯誤程式碼。失敗可能是由於不支援的操作(沒有支援的模式能夠處理請求的操作),或者是由匹配模式的 ->exec() 掛鉤返回的錯誤引起的。

unsigned int nand_subop_get_addr_start_off(const struct nand_subop *subop, unsigned int instr_idx)

獲取地址陣列中的起始偏移量

引數

const struct nand_subop *subop

整個子操作

unsigned int instr_idx

子操作內部指令的索引

描述

在驅動程式開發期間,人們可能會試圖直接使用地址指令的 ->addr.addrs 欄位。這是錯誤的,因為地址指令可能會被分割。

給定一個地址指令,返回要發出的第一個週期的偏移量。

unsigned int nand_subop_get_num_addr_cyc(const struct nand_subop *subop, unsigned int instr_idx)

獲取要斷言的剩餘地址週期數

引數

const struct nand_subop *subop

整個子操作

unsigned int instr_idx

子操作內部指令的索引

描述

在驅動程式開發期間,人們可能會試圖直接使用資料指令的 ->addr->naddrs 欄位。這是錯誤的,因為指令可能會被分割。

給定一個地址指令,返回要發出的地址週期數。

unsigned int nand_subop_get_data_start_off(const struct nand_subop *subop, unsigned int instr_idx)

獲取資料陣列中的起始偏移量

引數

const struct nand_subop *subop

整個子操作

unsigned int instr_idx

子操作內部指令的索引

描述

在驅動程式開發期間,人們可能會試圖直接使用資料指令的 ->data->buf.{in,out} 欄位。這是錯誤的,因為資料指令可能會被分割。

給定一個數據指令,返回要從其開始的偏移量。

unsigned int nand_subop_get_data_len(const struct nand_subop *subop, unsigned int instr_idx)

獲取要檢索的位元組數

引數

const struct nand_subop *subop

整個子操作

unsigned int instr_idx

子操作內部指令的索引

描述

在驅動程式開發期間,人們可能會試圖直接使用資料指令的 ->data->len 欄位。這是錯誤的,因為資料指令可能會被分割。

返回要傳送/接收的資料塊的長度。

int nand_reset(struct nand_chip *chip, int chipnr)

重置和初始化NAND裝置

引數

struct nand_chip *chip

NAND 晶片

int chipnr

內部晶片ID

描述

儲存時序資料結構,然後應用SDR時序模式0(有關詳細資訊,請參閱nand_reset_interface),執行重置操作,然後應用回先前的時序。

成功時返回 0,否則返回負錯誤程式碼。

int nand_check_erased_ecc_chunk(void *data, int datalen, void *ecc, int ecclen, void *extraoob, int extraooblen, int bitflips_threshold)

檢查ECC塊是否包含(幾乎)只有0xff資料

引數

void *data

要測試的資料緩衝區

int datalen

資料長度

void *ecc

ECC緩衝區

int ecclen

ECC長度

void *extraoob

額外的OOB緩衝區

int extraooblen

額外的OOB長度

int bitflips_threshold

最大位元翻轉數

描述

檢查資料緩衝區及其關聯的ECC和OOB資料是否僅包含0xff模式,這意味著底層區域已被擦除並且可以進行程式設計。bitflips_threshold指定在認為該區域未被擦除之前的最大位元翻轉數。

返回小於或等於bitflips_threshold的正位元翻轉數,或返回-ERROR_CODE表示超過閾值的位元翻轉數。如果成功,則傳遞的緩衝區將填充0xff。

注意

1/ ECC演算法適用於預定義的塊大小,這些塊大小通常

與NAND頁面大小不同。修復位元翻轉時,ECC引擎將報告每個塊的錯誤數,並且NAND核心基礎結構希望您返回整個頁面的最大位元翻轉數。這就是為什麼您應該始終在單個塊上使用此函式,而不是在整個頁面上使用此函式的原因。檢查每個塊後,應相應地更新max_bitflips值。

2/ 檢查擦除頁面中的位元翻轉時,您不僅應該檢查

有效負載資料,還應檢查其關聯的ECC資料,因為使用者可能已將幾乎所有位元都程式設計為1,但只有少數幾個。在這種情況下,我們不應將該塊視為已擦除,並且檢查ECC位元組可以防止這種情況發生。

3/ extraoob 引數是可選的,如果您的某些OOB

資料受ECC引擎保護,則應使用它。如果您支援子頁面並且想要將一些額外的OOB資料附加到ECC塊,也可以使用它。

int nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, int page)

[內部] 讀取沒有ecc的原始頁面資料

引數

struct nand_chip *chip

NAND晶片資訊結構

uint8_t *buf

用於儲存讀取資料的緩衝區

int oob_required

呼叫者需要將OOB資料讀取到chip->oob_poi

int page

要讀取的頁碼

描述

不適用於使用特殊oob佈局的綜合症計算ECC控制器。

int nand_monolithic_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page)

原始模式下的整體頁面讀取

引數

struct nand_chip *chip

NAND晶片資訊結構

u8 *buf

用於儲存讀取資料的緩衝區

int oob_required

呼叫者需要將OOB資料讀取到chip->oob_poi

int page

要讀取的頁碼

描述

這是一個原始頁面讀取,即沒有任何錯誤檢測/糾正。整體意味著我們請求將所有相關資料(主資料加上最終的OOB)載入到NAND快取中,並在單個操作中透過匯流排傳送(從NAND晶片到NAND控制器)。這是nand_read_page_raw() 的替代方法,後者首先讀取主資料,如果也請求OOB資料,則在總線上讀取更多資料。

int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf, int oob_required, int page)

硬體ECC頁面讀取,從OOB區域讀取ECC資料

引數

struct nand_chip *chip

NAND晶片資訊結構

uint8_t *buf

用於儲存讀取資料的緩衝區

int oob_required

呼叫者需要將OOB資料讀取到chip->oob_poi

int page

要讀取的頁碼

描述

用於大頁面晶片的硬體ECC,需要從OOB中提取ECC資料,然後再讀取實際資料。

int nand_read_oob_std(struct nand_chip *chip, int page)

[可替換] 最常用的OOB資料讀取函式

引數

struct nand_chip *chip

NAND晶片資訊結構

int page

要讀取的頁碼

int nand_write_oob_std(struct nand_chip *chip, int page)

[可替換] 最常用的OOB資料寫入函式

引數

struct nand_chip *chip

NAND晶片資訊結構

int page

要寫入的頁碼

int nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page)

[內部] 原始頁寫入函式

引數

struct nand_chip *chip

NAND晶片資訊結構

const uint8_t *buf

資料緩衝區

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

描述

不適用於使用特殊oob佈局的綜合症計算ECC控制器。

int nand_monolithic_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page)

原始模式下的整體頁寫入

引數

struct nand_chip *chip

NAND晶片資訊結構

const u8 *buf

要寫入的資料緩衝區

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

描述

這是一個原始頁寫入,即沒有任何錯誤檢測/糾正。 整體表示我們正在請求所有相關資料(主資料和最終OOB)透過匯流排傳送,並以單個操作有效地程式設計到NAND晶片陣列中。 這是nand_write_page_raw()的替代方案,它首先發送主資料,然後最終透過在NAND總線上鎖存更多資料週期來發送OOB資料,最後傳送程式命令以同步NAND晶片快取。

int rawnand_dt_parse_gpio_cs(struct device *dev, struct gpio_desc ***cs_array, unsigned int *ncs_array)

解析控制器的gpio-cs屬性

引數

struct device *dev

將被解析的裝置。 也用於託管分配。

struct gpio_desc ***cs_array

成功分配的GPIO描述符指標陣列

unsigned int *ncs_array

成功更新的**cs_array**中的條目數。 **返回** 成功時返回0,否則返回錯誤。

int nand_ecc_choose_conf(struct nand_chip *chip, const struct nand_ecc_caps *caps, int oobavail)

設定ECC強度和ECC步長

引數

struct nand_chip *chip

NAND晶片資訊結構

const struct nand_ecc_caps *caps

ECC引擎能力資訊結構

int oobavail

ECC引擎可以使用的OOB大小

描述

根據以下邏輯選擇ECC配置。

  1. 如果ECC步長和ECC強度都已設定(通常由DT設定),則檢查此控制器是否支援。

  2. 如果使用者提供了nand-ecc-maximize屬性,則選擇最大ECC強度。

  3. 否則,嘗試使ECC步長和ECC強度最接近晶片的要求。 如果可用的OOB大小不符合晶片的要求,則回退到最大ECC步長和ECC強度。

成功後,將設定所選的ECC設定。

int nand_scan_with_ids(struct nand_chip *chip, unsigned int maxchips, struct nand_flash_dev *ids)

[NAND介面] 掃描NAND裝置

引數

struct nand_chip *chip

NAND 晶片物件

unsigned int maxchips

要掃描的晶片數量。

struct nand_flash_dev *ids

可選的Flash ID表

描述

這會用預設值填充所有未初始化的函式指標。 讀取Flash ID,並用適當的值填充mtd/chip結構。

void nand_cleanup(struct nand_chip *chip)

[NAND介面] 釋放NAND裝置持有的資源

引數

struct nand_chip *chip

NAND 晶片物件

提供的內部函式

本章包含NAND驅動程式內部函式的自動生成文件。 每個函式都有一個簡短的描述,並標有[XXX]識別符號。 有關說明,請參見“文件提示”一章。 標有[DEFAULT]的函式可能與板驅動程式開發人員相關。

void nand_release_device(struct nand_chip *chip)

[通用] 釋放晶片

引數

struct nand_chip *chip

NAND 晶片物件

描述

釋放晶片鎖並喚醒任何等待裝置的人。

int nand_bbm_get_next_page(struct nand_chip *chip, int page)

獲取壞塊標記的下一頁

引數

struct nand_chip *chip

NAND 晶片物件

int page

開始檢查壞塊標記使用的第一頁

描述

返回一個整數,該整數對應於塊內的頁偏移量,用於儲存壞塊標記的頁。 如果沒有更多頁面可用,則返回-EINVAL。

int nand_block_bad(struct nand_chip *chip, loff_t ofs)

[預設] 從晶片讀取壞塊標記

引數

struct nand_chip *chip

NAND 晶片物件

loff_t ofs

從裝置起始位置的偏移量

描述

檢查塊是否損壞。

bool nand_region_is_secured(struct nand_chip *chip, loff_t offset, u64 size)

檢查區域是否安全

引數

struct nand_chip *chip

NAND 晶片物件

loff_t offset

要檢查的區域的偏移量

u64 size

要檢查的區域的大小

描述

透過將偏移量和大小與從DT獲得的受保護區域列表進行比較,來檢查該區域是否受保護。 如果該區域受保護,則返回true,否則返回false。

void nand_get_device(struct nand_chip *chip)

[通用] 獲取所選訪問的晶片

引數

struct nand_chip *chip

NAND 晶片結構體

描述

鎖定裝置及其控制器以進行獨佔訪問

int nand_check_wp(struct nand_chip *chip)

[通用] 檢查晶片是否受到防寫

引數

struct nand_chip *chip

NAND 晶片物件

描述

檢查裝置是否受到防寫。 該函式期望已選擇裝置。

uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, struct mtd_oob_ops *ops)

[內部] 將客戶端緩衝區傳輸到oob

引數

struct nand_chip *chip

NAND 晶片物件

uint8_t *oob

oob資料緩衝區

size_t len

oob資料寫入長度

struct mtd_oob_ops *ops

oob ops結構

int nand_do_write_oob(struct nand_chip *chip, loff_t to, struct mtd_oob_ops *ops)

[MTD介面] NAND寫入帶外

引數

struct nand_chip *chip

NAND 晶片物件

loff_t to

要寫入的偏移量

struct mtd_oob_ops *ops

oob操作描述結構

描述

NAND寫入帶外。

int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)

[預設] 透過壞塊標記將塊標記為壞塊

引數

struct nand_chip *chip

NAND 晶片物件

loff_t ofs

從裝置起始位置的偏移量

描述

這是預設實現,可以由硬體特定的驅動程式覆蓋。 它提供了將壞塊標記寫入塊的詳細資訊。

int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs)

透過更新BBM來標記塊

引數

struct nand_chip *chip

NAND 晶片物件

loff_t ofs

要標記為壞塊的塊的偏移量

int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)

將塊標記為壞塊

引數

struct nand_chip *chip

NAND 晶片物件

loff_t ofs

從裝置起始位置的偏移量

描述

此函式執行通用的NAND壞塊標記步驟(即,壞塊表和/或標記)。 我們只允許硬體驅動程式指定如何將壞塊標記寫入OOB(chip->legacy.block_markbad)。

我們按以下順序嘗試操作

  1. 擦除受影響的塊,以允許乾淨地寫入OOB標記

  2. 將壞塊標記寫入受影響塊的OOB區域(除非存在標誌NAND_BBT_NO_OOB_BBM)

  3. 更新BBT

請注意,我們保留在(2)或(3)中遇到的第一個錯誤,完成這些過程,並在最後轉儲該錯誤。

int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)

[通用] 檢查塊是否標記為保留。

引數

struct mtd_info *mtd

MTD裝置結構

loff_t ofs

從裝置起始位置的偏移量

描述

檢查該塊是否標記為保留。

int nand_block_checkbad(struct nand_chip *chip, loff_t ofs, int allowbbt)

[通用] 檢查塊是否標記為壞塊

引數

struct nand_chip *chip

NAND 晶片物件

loff_t ofs

從裝置起始位置的偏移量

int allowbbt

1,如果允許訪問 bbt 區域

描述

檢查塊是否損壞。可以透過讀取壞塊表或呼叫掃描函式來檢查。

void panic_nand_wait(struct nand_chip *chip, unsigned long timeo)

[通用] 等待命令完成

引數

struct nand_chip *chip

NAND 晶片結構體

unsigned long timeo

超時

描述

等待命令完成。這是 nand_wait 的輔助函式,用於在中斷上下文中呼叫。當發生 panic 並嘗試透過 mtdoops 寫入 oops 時可能會發生這種情況。

int nand_reset_interface(struct nand_chip *chip, int chipnr)

重置資料介面和時序

引數

struct nand_chip *chip

NAND 晶片

int chipnr

內部晶片ID

描述

將資料介面和時序重置為 ONFI 模式 0。

成功返回 0,否則返回負錯誤程式碼。

int nand_setup_interface(struct nand_chip *chip, int chipnr)

設定最佳資料介面和時序

引數

struct nand_chip *chip

NAND 晶片

int chipnr

內部晶片ID

描述

配置晶片和驅動程式報告的最佳資料介面和 NAND 時序。

成功返回 0,否則返回負錯誤程式碼。

int nand_choose_best_sdr_timings(struct nand_chip *chip, struct nand_interface_config *iface, struct nand_sdr_timings *spec_timings)

選擇 NAND 控制器和 NAND 晶片都支援的最佳 SDR 時序

引數

struct nand_chip *chip

NAND晶片

struct nand_interface_config *iface

介面配置(最終可以更新)

struct nand_sdr_timings *spec_timings

特定時序,當不符合 ONFI 規範時

描述

如果提供了特定時序,則使用它們。否則,從 ONFI 資訊中檢索支援的時序模式。

int nand_choose_best_nvddr_timings(struct nand_chip *chip, struct nand_interface_config *iface, struct nand_nvddr_timings *spec_timings)

選擇 NAND 控制器和 NAND 晶片都支援的最佳 NVDDR 時序

引數

struct nand_chip *chip

NAND晶片

struct nand_interface_config *iface

介面配置(最終可以更新)

struct nand_nvddr_timings *spec_timings

特定時序,當不符合 ONFI 規範時

描述

如果提供了特定時序,則使用它們。否則,從 ONFI 資訊中檢索支援的時序模式。

int nand_choose_best_timings(struct nand_chip *chip, struct nand_interface_config *iface)

選擇 NAND 控制器和 NAND 晶片都支援的最佳 NVDDR 或 SDR 時序

引數

struct nand_chip *chip

NAND晶片

struct nand_interface_config *iface

介面配置(最終可以更新)

描述

如果提供了特定時序,則使用它們。否則,從 ONFI 資訊中檢索支援的時序模式。

int nand_choose_interface_config(struct nand_chip *chip)

查詢最佳資料介面和時序

引數

struct nand_chip *chip

NAND 晶片

描述

查詢晶片和驅動程式支援的最佳資料介面和 NAND 時序。最終讓 NAND 製造商驅動程式提出自己的時序集。

在此函式之後,nand_chip->interface_config 使用可用的最佳時序模式進行初始化。

成功返回 0,否則返回負錯誤程式碼。

int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs, unsigned int offset_in_page)

填充地址的列週期

引數

struct nand_chip *chip

NAND 晶片

u8 *addrs

要填充的地址週期數組

unsigned int offset_in_page

頁內偏移量

描述

根據 NAND 匯流排寬度和頁面大小,填充 **addrs** 欄位的第一個或前兩個位元組。

返回編碼列所需的週期數,或者在其中一個引數無效的情況下返回負錯誤程式碼。

int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, unsigned int len)

執行 READ PARAMETER PAGE 操作

引數

struct nand_chip *chip

NAND 晶片

u8 page

要讀取的引數頁

void *buf

用於儲存資料的緩衝區

unsigned int len

緩衝區長度

描述

此函式發出 READ PARAMETER PAGE 操作。此函式不選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_set_features_op(struct nand_chip *chip, u8 feature, const void *data)

執行 SET FEATURES 操作

引數

struct nand_chip *chip

NAND 晶片

u8 feature

功能 ID

const void *data

4 位元組資料

描述

此函式傳送 SET FEATURES 命令並等待 NAND 準備就緒後再返回。此函式不選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

int nand_get_features_op(struct nand_chip *chip, u8 feature, void *data)

執行 GET FEATURES 操作

引數

struct nand_chip *chip

NAND 晶片

u8 feature

功能 ID

void *data

4 位元組資料

描述

此函式傳送 GET FEATURES 命令並等待 NAND 準備就緒後再返回。此函式不選擇/取消選擇 CS 線。

成功時返回 0,否則返回負錯誤程式碼。

struct nand_op_parser_ctx

解析器使用的上下文

定義:

struct nand_op_parser_ctx {
    const struct nand_op_instr *instrs;
    unsigned int ninstrs;
    struct nand_subop subop;
};

成員

instrs

必須定址的所有指令的陣列

ninstrs

instrs 陣列的長度

子操作

要傳遞給 NAND 控制器的子操作

描述

核心使用此結構將 NAND 操作拆分為可由 NAND 控制器處理的子操作。

bool nand_op_parser_must_split_instr(const struct nand_op_parser_pattern_elem *pat, const struct nand_op_instr *instr, unsigned int *start_offset)

檢查是否必須拆分指令

引數

const struct nand_op_parser_pattern_elem *pat

與 **instr** 匹配的解析器模式元素

const struct nand_op_instr *instr

指向要檢查的指令的指標

unsigned int *start_offset

這是一個輸入/輸出引數。如果 **instr** 已經被拆分,則 **start_offset** 是起始偏移量(地址週期或資料緩衝區中的偏移量)。相反,如果函式返回 true(即,必須拆分 instr),則此引數將更新為指向尚未處理的第一個資料/地址週期。

描述

某些 NAND 控制器受到限制,無法透過唯一操作傳送 X 地址週期,或者無法同時讀取/寫入超過 Y 位元組。在這種情況下,將不適合單個控制器操作的指令拆分為兩個或多個塊。

如果必須拆分指令,則返回 true,否則返回 false。**start_offset** 引數也會更新為下一組指令必須開始的偏移量(如果是地址或資料指令)。

bool nand_op_parser_match_pat(const struct nand_op_parser_pattern *pat, struct nand_op_parser_ctx *ctx)

檢查模式是否與解析器上下文中剩餘的指令匹配

引數

const struct nand_op_parser_pattern *pat

要測試的模式

struct nand_op_parser_ctx *ctx

要與模式 **pat** 匹配的解析器上下文結構

描述

檢查 **pat** 是否與 **ctx** 中剩餘的指令集或子集匹配。如果匹配,則返回 true,否則返回 false。當返回 true 時,**ctx->subop** 將更新為要傳遞給控制器驅動程式的指令集。

int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param)

執行 GET_FEATURE 的包裝器

引數

struct nand_chip *chip

NAND晶片資訊結構

int addr

功能地址

u8 *subfeature_param

子功能引數,一個四位元組陣列

描述

成功返回 0,否則返回負錯誤。如果操作無法處理,則返回 -ENOTSUPP。

int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param)

執行 SET_FEATURE 的包裝器

引數

struct nand_chip *chip

NAND晶片資訊結構

int addr

功能地址

u8 *subfeature_param

子功能引數,一個四位元組陣列

描述

成功返回 0,否則返回負錯誤。如果操作無法處理,則返回 -ENOTSUPP。

int nand_check_erased_buf(void *buf, int len, int bitflips_threshold)

檢查緩衝區是否包含(幾乎)只有 0xff 資料

引數

void *buf

要測試的緩衝區

int len

緩衝區長度

int bitflips_threshold

最大位元翻轉數

描述

檢查緩衝區是否僅包含 0xff,這意味著底層區域已被擦除並準備好進行程式設計。bitflips_threshold 指定在認為該區域未擦除之前允許的最大位翻轉次數。返回一個小於或等於 bitflips_threshold 的正數位翻轉次數,或者返回 -ERROR_CODE 表示位翻轉超過閾值。

注意

此函式的邏輯是從 memweight 實現中提取的,只是 nand_check_erased_buf 函式會在位翻轉次數超過 bitflips_threshold 值時在測試整個緩衝區之前退出。

int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, int oob_required, int page)

虛擬讀取原始頁面函式

引數

struct nand_chip *chip

NAND晶片資訊結構

u8 *buf

用於儲存讀取資料的緩衝區

int oob_required

呼叫者需要將OOB資料讀取到chip->oob_poi

int page

要讀取的頁碼

描述

無條件地返回 -ENOTSUPP。

int nand_read_page_raw_syndrome(struct nand_chip *chip, uint8_t *buf, int oob_required, int page)

[內部] 讀取沒有ecc的原始頁面資料

引數

struct nand_chip *chip

NAND晶片資訊結構

uint8_t *buf

用於儲存讀取資料的緩衝區

int oob_required

呼叫者需要將OOB資料讀取到chip->oob_poi

int page

要讀取的頁碼

描述

即使未使用 OOB,我們也需要特殊的 oob 佈局和處理。

int nand_read_page_swecc(struct nand_chip *chip, uint8_t *buf, int oob_required, int page)

[可替換] 基於軟體 ECC 的頁面讀取函式

引數

struct nand_chip *chip

NAND晶片資訊結構

uint8_t *buf

用於儲存讀取資料的緩衝區

int oob_required

呼叫者需要將OOB資料讀取到chip->oob_poi

int page

要讀取的頁碼

int nand_read_subpage(struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, int page)

[可替換] 基於 ECC 的子頁面讀取函式

引數

struct nand_chip *chip

NAND晶片資訊結構

uint32_t data_offs

請求的資料在頁面內的偏移量

uint32_t readlen

資料長度

uint8_t *bufpoi

用於儲存讀取資料的緩衝區

int page

要讀取的頁碼

int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, int oob_required, int page)

[可替換] 基於硬體 ECC 的頁面讀取函式

引數

struct nand_chip *chip

NAND晶片資訊結構

uint8_t *buf

用於儲存讀取資料的緩衝區

int oob_required

呼叫者需要將OOB資料讀取到chip->oob_poi

int page

要讀取的頁碼

描述

不適用於需要特殊 oob 佈局的 syndrome 計算 ECC 控制器。

int nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf, int oob_required, int page)

[可替換] 基於硬體 ECC 校驗位的頁面讀取

引數

struct nand_chip *chip

NAND晶片資訊結構

uint8_t *buf

用於儲存讀取資料的緩衝區

int oob_required

呼叫者需要將OOB資料讀取到chip->oob_poi

int page

要讀取的頁碼

描述

硬體生成器自動計算錯誤校驗位。因此,我們需要一個特殊的 oob 佈局和處理。

uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, struct mtd_oob_ops *ops, size_t len)

[內部] 將 oob 傳輸到客戶端緩衝區

引數

struct nand_chip *chip

NAND 晶片物件

uint8_t *oob

oob 目標地址

struct mtd_oob_ops *ops

oob ops結構

size_t len

要傳輸的 oob 的大小

int nand_setup_read_retry(struct nand_chip *chip, int retry_mode)

[內部] 設定 READ RETRY 模式

引數

struct nand_chip *chip

NAND 晶片物件

int retry_mode

要使用的重試模式

描述

一些供應商提供了一個特殊命令來移動 Vt 閾值,當頁面中存在太多位翻轉時(即 ECC 錯誤)使用。設定新閾值後,主機應重試讀取頁面。

int nand_do_read_ops(struct nand_chip *chip, loff_t from, struct mtd_oob_ops *ops)

[內部] 使用 ECC 讀取資料

引數

struct nand_chip *chip

NAND 晶片物件

loff_t from

讀取的偏移量

struct mtd_oob_ops *ops

oob ops結構

描述

內部函式。在持有 chip 的情況下呼叫。

int nand_read_oob_syndrome(struct nand_chip *chip, int page)

[可替換] 用於帶有校驗位的 HW ECC 的 OOB 資料讀取函式

引數

struct nand_chip *chip

NAND晶片資訊結構

int page

要讀取的頁碼

int nand_write_oob_syndrome(struct nand_chip *chip, int page)

[可替換] 用於帶有校驗位的 HW ECC 的 OOB 資料寫入函式 - 僅適用於大頁面快閃記憶體

引數

struct nand_chip *chip

NAND晶片資訊結構

int page

要寫入的頁碼

int nand_do_read_oob(struct nand_chip *chip, loff_t from, struct mtd_oob_ops *ops)

[內部] NAND 讀取帶外資料

引數

struct nand_chip *chip

NAND 晶片物件

loff_t from

讀取的偏移量

struct mtd_oob_ops *ops

oob 操作描述結構

描述

從備用區域讀取 NAND 帶外資料。

int nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)

[MTD 介面] NAND 讀取資料和/或帶外資料

引數

struct mtd_info *mtd

MTD裝置結構

loff_t from

讀取的偏移量

struct mtd_oob_ops *ops

oob操作描述結構

描述

NAND 讀取資料和/或帶外資料。

int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, int oob_required, int page)

虛擬原始頁面寫入函式

引數

struct nand_chip *chip

NAND晶片資訊結構

const u8 *buf

資料緩衝區

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

描述

無條件地返回 -ENOTSUPP。

int nand_write_page_raw_syndrome(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page)

[內部] 原始頁寫入函式

引數

struct nand_chip *chip

NAND晶片資訊結構

const uint8_t *buf

資料緩衝區

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

描述

即使不檢查 ECC,我們也需要特殊的 oob 佈局和處理。

int nand_write_page_swecc(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page)

[可替換] 基於軟體 ECC 的頁面寫入函式

引數

struct nand_chip *chip

NAND晶片資訊結構

const uint8_t *buf

資料緩衝區

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

int nand_write_page_hwecc(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page)

[可替換] 基於硬體 ECC 的頁面寫入函式

引數

struct nand_chip *chip

NAND晶片資訊結構

const uint8_t *buf

資料緩衝區

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

int nand_write_subpage_hwecc(struct nand_chip *chip, uint32_t offset, uint32_t data_len, const uint8_t *buf, int oob_required, int page)

[可替換] 基於硬體 ECC 的子頁面寫入

引數

struct nand_chip *chip

NAND晶片資訊結構

uint32_t offset

頁面內子頁面的列地址

uint32_t data_len

資料長度

const uint8_t *buf

資料緩衝區

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

int nand_write_page_syndrome(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page)

[可替換] 基於硬體 ECC 校驗位的頁面寫入

引數

struct nand_chip *chip

NAND晶片資訊結構

const uint8_t *buf

資料緩衝區

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

描述

硬體生成器自動計算錯誤校驗位。因此,我們需要一個特殊的 oob 佈局和處理。

int nand_write_page(struct nand_chip *chip, uint32_t offset, int data_len, const uint8_t *buf, int oob_required, int page, int raw)

寫入一個頁面

引數

struct nand_chip *chip

NAND 晶片描述符

uint32_t offset

頁面內的地址偏移量

int data_len

要寫入的實際資料的長度

const uint8_t *buf

要寫入的資料

int oob_required

必須將chip->oob_poi寫入到OOB

int page

要寫入的頁碼

int raw

使用 write_page 的 _raw 版本

int nand_do_write_ops(struct nand_chip *chip, loff_t to, struct mtd_oob_ops *ops)

[內部] 使用 ECC 寫入 NAND

引數

struct nand_chip *chip

NAND 晶片物件

loff_t to

要寫入的偏移量

struct mtd_oob_ops *ops

oob 操作描述結構

描述

使用 ECC 寫入 NAND。

int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)

[MTD 介面] 使用 ECC 寫入 NAND

引數

struct mtd_info *mtd

MTD裝置結構

loff_t to

要寫入的偏移量

size_t len

要寫入的位元組數

size_t *retlen

指向用於儲存寫入位元組數的變數的指標

const uint8_t *buf

要寫入的資料

描述

使用 ECC 寫入 NAND。在中斷上下文中執行寫入時使用,例如,當在 panic 狀態下寫入 oops 時,可能會被 mtdoops 呼叫。

int nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)

[MTD 介面] NAND 寫入資料和/或帶外資料

引數

struct mtd_info *mtd

MTD裝置結構

loff_t to

要寫入的偏移量

struct mtd_oob_ops *ops

oob操作描述結構

int nand_erase(struct mtd_info *mtd, struct erase_info *instr)

[MTD 介面] 擦除塊

引數

struct mtd_info *mtd

MTD裝置結構

struct erase_info *instr

擦除指令

描述

擦除一個或多個塊。

int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt)

[內部] 擦除塊

引數

struct nand_chip *chip

NAND 晶片物件

struct erase_info *instr

擦除指令

int allowbbt

允許擦除 bbt 區域

描述

擦除一個或多個塊。

void nand_sync(struct mtd_info *mtd)

[MTD 介面] 同步

引數

struct mtd_info *mtd

MTD裝置結構

描述

同步實際上是一個等待晶片準備好的函式。

int nand_block_isbad(struct mtd_info *mtd, loff_t offs)

[MTD 介面] 檢查偏移量處的塊是否損壞

引數

struct mtd_info *mtd

MTD裝置結構

loff_t offs

相對於 MTD 起始位置的偏移量

int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)

[MTD 介面] 將給定偏移量處的塊標記為壞塊

引數

struct mtd_info *mtd

MTD裝置結構

loff_t ofs

相對於 MTD 起始位置的偏移量

int nand_suspend(struct mtd_info *mtd)

[MTD 介面] 掛起 NAND 快閃記憶體

引數

struct mtd_info *mtd

MTD裝置結構

描述

成功返回 0,否則返回負錯誤程式碼。

void nand_resume(struct mtd_info *mtd)

[MTD 介面] 恢復 NAND 快閃記憶體

引數

struct mtd_info *mtd

MTD裝置結構

void nand_shutdown(struct mtd_info *mtd)

[MTD 介面] 完成當前的 NAND 操作並阻止進一步的操作

引數

struct mtd_info *mtd

MTD裝置結構

int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)

[MTD 介面] 鎖定 NAND 快閃記憶體

引數

struct mtd_info *mtd

MTD裝置結構

loff_t ofs

偏移位元組地址

uint64_t len

要鎖定的位元組數(必須是塊/頁大小的倍數)

int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)

[MTD 介面] 解鎖 NAND 快閃記憶體

引數

struct mtd_info *mtd

MTD裝置結構

loff_t ofs

偏移位元組地址

uint64_t len

要解鎖的位元組數(必須是塊/頁大小的倍數)

int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, struct nand_flash_dev *table)

掃描 NAND 裝置

引數

struct nand_chip *chip

NAND 晶片物件

unsigned int maxchips

要掃描的晶片數量

struct nand_flash_dev *table

備用 NAND ID 表

描述

這是普通 nand_scan() 函式的第一階段。它讀取快閃記憶體 ID 並相應地設定 MTD 欄位。

這個輔助函式曾經直接從控制器驅動程式呼叫,這些驅動程式需要在 nand_scan_tail() 之前調整一些與 ECC 相關的引數。 這種分離阻止了在此階段進行動態分配,這很不方便,並且為了 ->init_ecc()/cleanup_ecc() 掛鉤的好處而被禁止。

int nand_check_ecc_caps(struct nand_chip *chip, const struct nand_ecc_caps *caps, int oobavail)

檢查預設 ECC 設定的合理性

引數

struct nand_chip *chip

NAND晶片資訊結構

const struct nand_ecc_caps *caps

ECC 容量資訊結構

int oobavail

ECC引擎可以使用的OOB大小

描述

當 ECC 步長大小和強度已經設定時,檢查它們是否受控制器支援,並且計算出的 ECC 位元組是否適合晶片的 OOB。 成功後,設定計算出的 ECC 位元組。

int nand_match_ecc_req(struct nand_chip *chip, const struct nand_ecc_caps *caps, int oobavail)

以最少的 ECC 位元組滿足晶片的要求

引數

struct nand_chip *chip

NAND晶片資訊結構

const struct nand_ecc_caps *caps

ECC引擎能力資訊結構

int oobavail

ECC引擎可以使用的OOB大小

描述

如果提供了晶片的 ECC 要求,請嘗試以最少的 ECC 位元組數(即,以最大數量的無 OOB 位元組)來滿足它。 成功後,將設定所選的 ECC 設定。

int nand_maximize_ecc(struct nand_chip *chip, const struct nand_ecc_caps *caps, int oobavail)

選擇可用的最大 ECC 強度

引數

struct nand_chip *chip

NAND晶片資訊結構

const struct nand_ecc_caps *caps

ECC引擎能力資訊結構

int oobavail

ECC引擎可以使用的OOB大小

描述

選擇控制器上支援的並且可以容納在晶片 OOB 中的最大 ECC 強度。 成功後,將設定所選的 ECC 設定。

int nand_scan_tail(struct nand_chip *chip)

掃描 NAND 裝置

引數

struct nand_chip *chip

NAND 晶片物件

描述

這是普通 nand_scan() 函式的第二階段。 它使用預設值填充所有未初始化的函式指標,並掃描壞塊表(如果適用)。

int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)

[通用] 檢查緩衝區中是否存在模式

引數

uint8_t *buf

要搜尋的緩衝區

int len

要搜尋的緩衝區的長度

int paglen

頁長度

struct nand_bbt_descr *td

搜尋模式描述符

描述

檢查給定位置是否存在模式。 用於搜尋壞塊表和好/壞塊識別符號。

int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)

[通用] 檢查緩衝區中是否存在模式

引數

uint8_t *buf

要搜尋的緩衝區

struct nand_bbt_descr *td

搜尋模式描述符

描述

檢查給定位置是否存在模式。 用於搜尋壞塊表和好/壞塊識別符號。 與 check_pattern 相同,但沒有可選的空檢查。

u32 add_marker_len(struct nand_bbt_descr *td)

計算資料區域中標記的長度

引數

struct nand_bbt_descr *td

用於計算的 BBT 描述符

描述

如果標記位於 OOB 區域中,則長度將為 0。

int read_bbt(struct nand_chip *this, uint8_t *buf, int page, int num, struct nand_bbt_descr *td, int offs)

[通用] 從頁面開始讀取壞塊表

引數

struct nand_chip *this

NAND 晶片物件

uint8_t *buf

臨時緩衝區

int page

起始頁面

int num

要讀取的 bbt 描述符的數量

struct nand_bbt_descr *td

bbt 描述表

int offs

表中塊號偏移量

描述

從頁面開始讀取壞塊表。

int read_abs_bbt(struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td, int chip)

[通用] 從給定頁面開始讀取壞塊表

引數

struct nand_chip *this

NAND 晶片物件

uint8_t *buf

臨時緩衝區

struct nand_bbt_descr *td

壞塊表的描述符

int chip

讀取特定晶片的表,-1 讀取所有晶片; 僅當設定了 NAND_BBT_PERCHIP 選項時才適用

描述

從給定頁面開始讀取所有晶片的壞塊表。 我們假設 bbt 位是連續的。

int scan_read_oob(struct nand_chip *this, uint8_t *buf, loff_t offs, size_t len)

[通用] 將資料+OOB 區域掃描到緩衝區

引數

struct nand_chip *this

NAND 晶片物件

uint8_t *buf

臨時緩衝區

loff_t offs

掃描的偏移量

size_t len

要讀取的資料區域的長度

描述

從資料+OOB 掃描讀取資料。 可能會遍歷多個頁面,在 buf 中交錯頁面、OOB、頁面、OOB... 完成傳輸並返回“最強”的 ECC 條件(錯誤或位翻轉)。 可能會在第一個(非 ECC)錯誤時退出。

void read_abs_bbts(struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)

[通用] 從給定頁開始讀取所有晶片的壞塊表

引數

struct nand_chip *this

NAND 晶片物件

uint8_t *buf

臨時緩衝區

struct nand_bbt_descr *td

壞塊表的描述符

struct nand_bbt_descr *md

壞塊表映象的描述符

描述

從給定頁開始讀取所有晶片的壞塊表。我們假設壞塊位是連續的。

int create_bbt(struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *bd, int chip)

[通用] 透過掃描裝置建立壞塊表

引數

struct nand_chip *this

NAND 晶片物件

uint8_t *buf

臨時緩衝區

struct nand_bbt_descr *bd

好/壞塊搜尋模式的描述符

int chip

為特定晶片建立表,-1 讀取所有晶片; 僅當設定了 NAND_BBT_PERCHIP 選項時適用

描述

透過掃描裝置以尋找給定的好/壞塊識別模式來建立壞塊表。

int search_bbt(struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td)

[通用] 掃描裝置以尋找特定的壞塊表

引數

struct nand_chip *this

NAND 晶片物件

uint8_t *buf

臨時緩衝區

struct nand_bbt_descr *td

壞塊表的描述符

描述

透過搜尋給定的識別模式來讀取壞塊表。搜尋從裝置開頭向上或從裝置末尾向下執行。搜尋始終從塊的開頭開始。如果給定了 NAND_BBT_PERCHIP 選項,則每個晶片都會搜尋一個包含該晶片壞塊資訊的 bbt。這對於支援某些 DOC 裝置是必要的。

bbt 識別模式位於塊中第一頁的 oob 區域中。

void search_read_bbts(struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)

[通用] 掃描裝置以尋找壞塊表

引數

struct nand_chip *this

NAND 晶片物件

uint8_t *buf

臨時緩衝區

struct nand_bbt_descr *td

壞塊表的描述符

struct nand_bbt_descr *md

壞塊表映象的描述符

描述

搜尋並讀取壞塊表。

int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chip)

獲取適合儲存 BBT 的第一個有效擦除塊

引數

struct nand_chip *this

NAND 裝置

struct nand_bbt_descr *td

BBT 描述

struct nand_bbt_descr *md

映象 BBT 描述符

int chip

CHIP 選擇器

描述

此函式返回一個正塊號,指向適合儲存 BBT 的有效擦除塊(即在為 BBT 保留的範圍內),或者如果所有塊都已使用或標記為壞塊,則返回 -ENOSPC。如果 td->pages[chip] 已經指向一個有效的塊,我們會重用它,否則我們會搜尋下一個有效的塊。

void mark_bbt_block_bad(struct nand_chip *this, struct nand_bbt_descr *td, int chip, int block)

將為 BBT 保留的塊之一標記為壞塊

引數

struct nand_chip *this

NAND 裝置

struct nand_bbt_descr *td

BBT 描述

int chip

CHIP 選擇器

int block

要標記的 BBT 塊

描述

為 BBT 保留的塊可能會變壞。此函式是一個幫助程式,用於將此類塊標記為壞塊。它負責更新記憶體中的 BBT,使用壞塊標記將塊標記為壞塊,並使相關的 td->pages[] 條目無效。

int write_bbt(struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)

[通用] (重新)寫入壞塊表

引數

struct nand_chip *this

NAND 晶片物件

uint8_t *buf

臨時緩衝區

struct nand_bbt_descr *td

壞塊表的描述符

struct nand_bbt_descr *md

壞塊表映象的描述符

int chipsel

特定晶片的選擇器,-1 表示全部

描述

(重新)寫入壞塊表。

int nand_memory_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)

[通用] 建立基於記憶體的壞塊表

引數

struct nand_chip *this

NAND 晶片物件

struct nand_bbt_descr *bd

好/壞塊搜尋模式的描述符

描述

該函式透過掃描裝置以查詢製造商/軟體標記的好/壞塊來建立基於記憶體的 bbt。

int check_create(struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *bd)

[通用] 如果需要,建立並寫入 bbt

引數

struct nand_chip *this

NAND 裝置

uint8_t *buf

臨時緩衝區

struct nand_bbt_descr *bd

好/壞塊搜尋模式的描述符

描述

該函式檢查先前呼叫 read_bbt 的結果,並在必要時建立/更新 bbt。 如果沒有找到晶片/裝置的 bbt,則需要建立。 如果缺少一個表或一個表的版本號小於另一個表,則需要更新。

int nand_update_bbt(struct nand_chip *this, loff_t offs)

更新壞塊表

引數

struct nand_chip *this

NAND 裝置

loff_t offs

新標記的塊的偏移量

描述

該函式更新壞塊表。

void mark_bbt_region(struct nand_chip *this, struct nand_bbt_descr *td)

[通用] 標記壞塊表區域

引數

struct nand_chip *this

NAND 裝置

struct nand_bbt_descr *td

壞塊表描述符

描述

壞塊表區域被標記為“壞”以防止意外擦除/寫入。 這些區域由標記 0x02 標識。

void verify_bbt_descr(struct nand_chip *this, struct nand_bbt_descr *bd)

驗證壞塊描述

引數

struct nand_chip *this

NAND 裝置

struct nand_bbt_descr *bd

要驗證的表

描述

此函式對壞塊描述表執行一些健全性檢查。

int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)

[NAND 介面] 掃描,查詢,讀取並可能建立壞塊表

引數

struct nand_chip *this

NAND 裝置

struct nand_bbt_descr *bd

好/壞塊搜尋模式的描述符

描述

該函式檢查是否已存在壞塊表。 如果沒有,它會掃描裝置以查詢製造商標記的好/壞塊,並將壞塊表寫入選定的位置。

壞塊表記憶體在這裡分配。 必須透過呼叫 nand_free_bbt 函式來釋放它。

int nand_create_badblock_pattern(struct nand_chip *this)

[內部] 建立 BBT 描述符結構

引數

struct nand_chip *this

要為其建立描述符的 NAND 晶片

描述

此函式基於 **this** 的屬性,分配並初始化一個用於 BBM 檢測的 nand_bbt_descr。 新的描述符儲存在 this->badblock_pattern 中。 因此,傳遞給此函式時,this->badblock_pattern 應為 NULL。

int nand_isreserved_bbt(struct nand_chip *this, loff_t offs)

[NAND 介面] 檢查一個塊是否被保留

引數

struct nand_chip *this

NAND 晶片物件

loff_t offs

裝置中的偏移量

int nand_isbad_bbt(struct nand_chip *this, loff_t offs, int allowbbt)

[NAND 介面] 檢查一個塊是否為壞塊

引數

struct nand_chip *this

NAND 晶片物件

loff_t offs

裝置中的偏移量

int allowbbt

允許訪問壞塊表區域

int nand_markbad_bbt(struct nand_chip *this, loff_t offs)

[NAND 介面] 在 BBT 中將一個塊標記為壞塊

引數

struct nand_chip *this

NAND 晶片物件

loff_t offs

壞塊的偏移量

致謝

以下人員為 NAND 驅動程式做出了貢獻

  1. Steven J. Hillsjhill@realitydiluted.com

  2. David Woodhousedwmw2@infradead.org

  3. Thomas Gleixnertglx@linutronix.de

許多使用者提供了錯誤修復,改進和幫助進行測試。非常感謝。

以下人員為本文件做出了貢獻

  1. Thomas Gleixnertglx@linutronix.de