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_featuresNAND 芯片支持设置/获取特性
supports_read_cacheNAND 芯片支持读取缓存操作
set_feature_list可以设置的特性的位图
get_feature_list可以获取的特性的位图
onfiONFI 特定参数
-
struct nand_id¶
NAND ID 结构
定义:
struct nand_id {
u8 data[NAND_MAX_ID_LEN];
int len;
};
成员
data包含 ID 字节的缓冲区。
lenID 长度。
-
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);
};
成员
stepinfosECC 步信息数组
nstepinfosECC 步信息数
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_typeECC 引擎类型
placementOOB 字节放置
algoECC 算法
steps每页的 ECC 步数
size每个 ECC 步的数据字节数
字节每个步的 ECC 字节数
total每页的 ECC 字节总数
strength每个 ECC 步可纠正的最大位数
prepad基于综合症的 ECC 生成器的填充信息
postpad基于综合症的 ECC 生成器的填充信息
optionsECC 特定选项(参见上面定义的 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_minALE 保持时间
tADL_minALE 到数据加载时间
tALS_minALE 设置时间
tAR_minALE 到 RE# 延迟
tCEA_maxCE# 访问时间
tCEH_minCE# 高电平保持时间
tCH_minCE# 保持时间
tCHZ_maxCE# 高电平到输出高阻抗
tCLH_minCLE 保持时间
tCLR_minCLE 到 RE# 延迟
tCLS_minCLE 设置时间
tCOH_minCE# 高电平到输出保持
tCS_minCE# 设置时间
tDH_min数据保持时间
tDS_min数据设置时间
tFEAT_max设置特性和获取特性的繁忙时间
tIR_min输出高阻抗到 RE# 低电平
tITC_max接口和时序模式更改时间
tRC_minRE# 周期时间
tREA_maxRE# 访问时间
tREH_minRE# 高电平保持时间
tRHOH_minRE# 高电平到输出保持
tRHW_minRE# 高电平到 WE# 低电平
tRHZ_maxRE# 高电平到输出高阻抗
tRLOH_minRE# 低电平到输出保持
tRP_minRE# 脉冲宽度
tRR_min就绪到 RE# 低电平(仅限数据)
tRST_max设备重置时间,从 R/B# 的下降沿到 R/B# 的上升沿测量。
tWB_maxWE# 高电平到 SR[6] 低电平
tWC_minWE# 周期时间
tWH_minWE# 高电平保持时间
tWHR_minWE# 高电平到 RE# 低电平
tWP_minWE# 脉冲宽度
tWW_minWP# 转换到 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_minDQ[7:0] 从 CLK 的访问窗口
tAC_maxDQ[7:0] 从 CLK 的访问窗口
tADL_minALE 到数据加载时间
tCAD_min命令、地址、数据延迟
tCAH_min命令/地址 DQ 保持时间
tCALH_minW/R_n、CLE 和 ALE 保持时间
tCALS_minW/R_n、CLE 和 ALE 设置时间
tCAS_min命令/地址 DQ 设置时间
tCEH_minCE# 高电平保持时间
tCH_minCE# 保持时间
tCK_min平均时钟周期时间
tCS_minCE# 设置时间
tDH_min数据保持时间
tDQSCK_minDQS 从 CLK 的访问窗口的开始
tDQSCK_maxDQS 从 CLK 的访问窗口的结束
tDQSD_min最小 W/R_n 低电平到 DQS/DQ 由设备驱动
tDQSD_max最大 W/R_n 低电平到 DQS/DQ 由设备驱动
tDQSHZ_maxW/R_n 高电平到 DQS/DQ 由设备三态
tDQSQ_maxDQS-DQ 倾斜,DQS 到最后一个 DQ 有效,每次访问
tDS_min数据设置时间
tDSC_minDQS 周期时间
tFEAT_max设置特性和获取特性的繁忙时间
tITC_max接口和时序模式更改时间
tQHS_max数据保持倾斜因子
tRHW_min数据输出周期到命令、地址或数据输入周期
tRR_min就绪到 RE# 低电平(仅限数据)
tRST_max设备重置时间,从 R/B# 的下降沿到 R/B# 的上升沿测量。
tWB_maxWE# 高电平到 SR[6] 低电平
tWHR_minWE# 高电平到 RE# 低电平
tWRCK_minW/R_n 低电平到数据输出周期
tWW_minWP# 转换到 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当 type 为
NAND_SDR_IFACE时使用它。timings.nvddr当 type 为
NAND_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;
};
成员
naddrsaddrs 数组的长度
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如果 type 是
NAND_OP_CMD_INSTR,则使用它ctx.addr如果 type 是
NAND_OP_ADDR_INSTR,则使用它ctx.data如果 type 是
NAND_OP_DATA_IN_INSTR或NAND_OP_DATA_OUT_INSTR,则使用它ctx.waitrdy如果 type 是
NAND_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指令数组
ninstrsinstrs 数组的长度
first_instr_start_off子操作的第一个指令的起始偏移量
last_instr_end_off子操作的最后一个指令的结束偏移量(不包括)
描述
first_instr_start_off 和 last_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模式元素数组
nelemselems 数组中模式元素的数量
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支持的模式数组
npatternspatterns 数组的长度
描述
解析器描述符只是一个支持的模式数组,每次 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要执行的指令数组
ninstrsinstrs 数组的长度
描述
将传递给 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 控制器的访问的锁
opsNAND 控制器操作。
supported_opNAND 控制器已知支持的操作,仅在初始检查后可由核心写入。
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制造商信息
opsNAND 芯片操作
legacy所有传统字段/钩子。如果您开发新的驱动程序,请甚至不要尝试使用这些字段/钩子中的任何一个,并且如果您正在修改使用这些字段/钩子的现有驱动程序,则应考虑重新设计驱动程序并避免使用它们。
options各种芯片选项。它们可以部分设置为通知 nand_scan 特殊功能。有关进一步说明,请参见定义。
current_interface_config当前使用的 NAND 接口配置
best_interface_config最适合 NAND 芯片和 NAND 控制器约束的最佳 NAND 接口配置。如果未设置,则必须使用默认的重置接口配置。
bbt_erase_shiftbbt 条目中的地址位数
bbt_options坏块表特定选项。此处使用的所有选项都必须来自 bbm.h。默认情况下,这些选项将复制到适当的 nand_bbt_descr 中。
badblockposoob 区域中的坏块标记位置
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_poidata_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在多个独立设备之间共享的硬件控制器结构
eccECC 控制器结构
priv芯片私有数据
-
const struct nand_interface_config *nand_get_interface_config(struct nand_chip *chip)¶
获取 NAND 芯片的当前接口配置
参数
struct nand_chip *chipNAND 芯片
-
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;
};
成员
nameNAND 芯片的可读名称
{unnamed_union}anonymous
{unnamed_struct}anonymous
mfr_id完整芯片 ID 数组的制造商 ID 部分 (指向与
id[0]相同的内存地址)dev_id完整芯片 ID 数组的设备 ID 部分 (指向与
id[1]相同的内存地址)id完整设备 ID 数组
pagesizeNAND 页的大小,单位为字节;如果为 0,则实际页大小(以及擦除块大小)将从扩展 NAND 芯片 ID 数组中确定
chipsize总芯片大小,单位为 MiB
erasesize擦除块大小,单位为字节 (如果为 0,则从扩展 ID 确定)
options存储各种芯片位选项
id_lenid 的有效长度。
oobsizeOOB 大小
ecc来自数据手册的 ECC 纠错能力和步长信息。
ecc.strength_ds来自数据手册的 ECC 纠错能力,与 nand_chip{} 中的 ecc_strength_ds 相同。
ecc.step_dsecc.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要检查的操作码
参数
struct nand_chip *chipNAND 芯片对象
描述
返回使缓存无效后的预分配页面缓冲区。驱动程序不希望分配自己的反弹缓冲区,但仍然需要用于特定操作(最常见的是仅读取 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 的位数
描述
将位从一个内存区域复制到另一个内存区域(允许重叠)。
参数
struct nand_chip *chipNAND 芯片对象
unsigned int cs要选择的 CS 线。请注意,此 CS id 始终来自芯片 PoV,而不是控制器 PoV
描述
选择一个 NAND 目标,以便在 chip 上执行的进一步操作将转到所选的 NAND 目标。
参数
struct nand_chip *chipNAND 芯片对象
描述
取消选择当前选择的 NAND 目标。取消选择目标后,在 chip 上执行的操作的结果未定义。
-
int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)¶
轮询 STATUS 寄存器,直到 RDY 位设置为 1
参数
struct nand_chip *chipNAND 芯片结构体
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 *chipNAND 芯片结构体
struct gpio_desc *gpiodR/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 *chipNAND 芯片
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 *chipNAND 芯片
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 *chipNAND 芯片
unsigned int page要读取的页
unsigned int offset_in_oobOOB 区域内的偏移量
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 *chipNAND 芯片
unsigned int page要写入的页
unsigned int offset_in_page页面内的偏移量
const void *buf包含要写入页面的数据的缓冲区
unsigned int len缓冲区长度
描述
此函数发出 PROG PAGE 操作的前半部分。此函数不会选择/取消选择 CS 线。
成功时返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
描述
此函数发出 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 *chipNAND 芯片
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 *chipNAND 芯片
unsigned int offset_in_page页面内的偏移量
const void *buf包含要发送到 NAND 的数据的缓冲区
unsigned int len缓冲区长度
bool force_8bit强制 8 位总线访问
描述
此函数发出 CHANGE WRITE COLUMN 操作。此函数不会选择/取消选择 CS 线。
成功时返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
u8 addr在READID命令之后要经过的地址周期数
void *buf用于存储ID的缓冲区
unsigned int len缓冲区长度
描述
此函数发送READID命令并读取NAND返回的ID。此函数不选择/取消选择CS线。
成功时返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
u8 *status用于存储NAND状态的输出变量
描述
此函数发送STATUS命令并读取NAND返回的状态。此函数不选择/取消选择CS线。
成功时返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
描述
此函数发送READ0命令以取消STATUS命令的效果,以避免仅读取状态,直到发送新的读取命令。
此函数不选择/取消选择CS线。
成功时返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
unsigned int eraseblock要擦除的块
描述
此函数发送ERASE命令并等待NAND准备就绪后返回。此函数不选择/取消选择CS线。
成功时返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
描述
此函数发送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 *chipNAND 芯片
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 *chipNAND 芯片
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 *chipNAND芯片
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 字段。这是错误的,因为数据指令可能会被分割。
返回要发送/接收的数据块的长度。
参数
struct nand_chip *chipNAND 芯片
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 *eccECC缓冲区
int ecclenECC长度
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
uint8_t *buf用于存储读取数据的缓冲区
int oob_required调用者需要将OOB数据读取到chip->oob_poi
int page要读取的页码
描述
用于大页面芯片的硬件ECC,需要从OOB中提取ECC数据,然后再读取实际数据。
参数
struct nand_chip *chipNAND芯片信息结构
int page要读取的页码
参数
struct nand_chip *chipNAND芯片信息结构
int page要写入的页码
-
int nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page)¶
[内部] 原始页写入函数
参数
struct nand_chip *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
const struct nand_ecc_caps *capsECC引擎能力信息结构
int oobavailECC引擎可以使用的OOB大小
描述
根据以下逻辑选择ECC配置。
如果ECC步长和ECC强度都已设置(通常由DT设置),则检查此控制器是否支持。
如果用户提供了nand-ecc-maximize属性,则选择最大ECC强度。
否则,尝试使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 *chipNAND 芯片对象
unsigned int maxchips要扫描的芯片数量。
struct nand_flash_dev *ids可选的Flash ID表
描述
这会用默认值填充所有未初始化的函数指针。 读取Flash ID,并用适当的值填充mtd/chip结构。
参数
struct nand_chip *chipNAND 芯片对象
提供的内部函数¶
本章包含NAND驱动程序内部函数的自动生成文档。 每个函数都有一个简短的描述,并标有[XXX]标识符。 有关说明,请参见“文档提示”一章。 标有[DEFAULT]的函数可能与板驱动程序开发人员相关。
参数
struct nand_chip *chipNAND 芯片对象
描述
释放芯片锁并唤醒任何等待设备的人。
参数
struct nand_chip *chipNAND 芯片对象
int page开始检查坏块标记使用的第一页
描述
返回一个整数,该整数对应于块内的页偏移量,用于存储坏块标记的页。 如果没有更多页面可用,则返回-EINVAL。
参数
struct nand_chip *chipNAND 芯片对象
loff_t ofs从设备起始位置的偏移量
描述
检查块是否损坏。
参数
struct nand_chip *chipNAND 芯片对象
loff_t offset要检查的区域的偏移量
u64 size要检查的区域的大小
描述
通过将偏移量和大小与从DT获得的受保护区域列表进行比较,来检查该区域是否受保护。 如果该区域受保护,则返回true,否则返回false。
参数
struct nand_chip *chipNAND 芯片结构体
描述
锁定设备及其控制器以进行独占访问
参数
struct nand_chip *chipNAND 芯片对象
描述
检查设备是否受到写保护。 该函数期望已选择设备。
-
uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, struct mtd_oob_ops *ops)¶
[内部] 将客户端缓冲区传输到oob
参数
struct nand_chip *chipNAND 芯片对象
uint8_t *ooboob数据缓冲区
size_t lenoob数据写入长度
struct mtd_oob_ops *opsoob ops结构
参数
struct nand_chip *chipNAND 芯片对象
loff_t to要写入的偏移量
struct mtd_oob_ops *opsoob操作描述结构
描述
NAND写入带外。
参数
struct nand_chip *chipNAND 芯片对象
loff_t ofs从设备起始位置的偏移量
描述
这是默认实现,可以由硬件特定的驱动程序覆盖。 它提供了将坏块标记写入块的详细信息。
参数
struct nand_chip *chipNAND 芯片对象
loff_t ofs要标记为坏块的块的偏移量
参数
struct nand_chip *chipNAND 芯片对象
loff_t ofs从设备起始位置的偏移量
描述
此函数执行通用的NAND坏块标记步骤(即,坏块表和/或标记)。 我们只允许硬件驱动程序指定如何将坏块标记写入OOB(chip->legacy.block_markbad)。
我们按以下顺序尝试操作
擦除受影响的块,以允许干净地写入OOB标记
将坏块标记写入受影响块的OOB区域(除非存在标志NAND_BBT_NO_OOB_BBM)
更新BBT
请注意,我们保留在(2)或(3)中遇到的第一个错误,完成这些过程,并在最后转储该错误。
-
int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)¶
[通用] 检查块是否标记为保留。
参数
struct mtd_info *mtdMTD设备结构
loff_t ofs从设备起始位置的偏移量
描述
检查该块是否标记为保留。
参数
struct nand_chip *chipNAND 芯片对象
loff_t ofs从设备起始位置的偏移量
int allowbbt1,如果允许访问 bbt 区域
描述
检查块是否损坏。可以通过读取坏块表或调用扫描函数来检查。
参数
struct nand_chip *chipNAND 芯片结构体
unsigned long timeo超时
描述
等待命令完成。这是 nand_wait 的辅助函数,用于在中断上下文中调用。当发生 panic 并尝试通过 mtdoops 写入 oops 时可能会发生这种情况。
参数
struct nand_chip *chipNAND 芯片
int chipnr内部芯片ID
描述
将数据接口和时序重置为 ONFI 模式 0。
成功返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
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 *chipNAND芯片
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 *chipNAND芯片
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 *chipNAND芯片
struct nand_interface_config *iface接口配置(最终可以更新)
描述
如果提供了特定时序,则使用它们。否则,从 ONFI 信息中检索支持的时序模式。
参数
struct nand_chip *chipNAND 芯片
描述
查找芯片和驱动程序支持的最佳数据接口和 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 *chipNAND 芯片
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 *chipNAND 芯片
u8 page要读取的参数页
void *buf用于存储数据的缓冲区
unsigned int len缓冲区长度
描述
此函数发出 READ PARAMETER PAGE 操作。此函数不选择/取消选择 CS 线。
成功时返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
u8 feature功能 ID
const void *data4 字节数据
描述
此函数发送 SET FEATURES 命令并等待 NAND 准备就绪后再返回。此函数不选择/取消选择 CS 线。
成功时返回 0,否则返回负错误代码。
参数
struct nand_chip *chipNAND 芯片
u8 feature功能 ID
void *data4 字节数据
描述
此函数发送 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必须寻址的所有指令的数组
ninstrsinstrs 数组的长度
子操作要传递给 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** 将更新为要传递给控制器驱动程序的指令集。
参数
struct nand_chip *chipNAND芯片信息结构
int addr功能地址
u8 *subfeature_param子功能参数,一个四字节数组
描述
成功返回 0,否则返回负错误。如果操作无法处理,则返回 -ENOTSUPP。
参数
struct nand_chip *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND 芯片对象
uint8_t *ooboob 目标地址
struct mtd_oob_ops *opsoob ops结构
size_t len要传输的 oob 的大小
参数
struct nand_chip *chipNAND 芯片对象
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 *chipNAND 芯片对象
loff_t from读取的偏移量
struct mtd_oob_ops *opsoob ops结构
描述
内部函数。在持有 chip 的情况下调用。
参数
struct nand_chip *chipNAND芯片信息结构
int page要读取的页码
-
int nand_write_oob_syndrome(struct nand_chip *chip, int page)¶
[可替换] 用于带有校验位的 HW ECC 的 OOB 数据写入函数 - 仅适用于大页面闪存
参数
struct nand_chip *chipNAND芯片信息结构
int page要写入的页码
-
int nand_do_read_oob(struct nand_chip *chip, loff_t from, struct mtd_oob_ops *ops)¶
[内部] NAND 读取带外数据
参数
struct nand_chip *chipNAND 芯片对象
loff_t from读取的偏移量
struct mtd_oob_ops *opsoob 操作描述结构
描述
从备用区域读取 NAND 带外数据。
-
int nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)¶
[MTD 接口] NAND 读取数据和/或带外数据
参数
struct mtd_info *mtdMTD设备结构
loff_t from读取的偏移量
struct mtd_oob_ops *opsoob操作描述结构
描述
NAND 读取数据和/或带外数据。
-
int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, int oob_required, int page)¶
虚拟原始页面写入函数
参数
struct nand_chip *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND芯片信息结构
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 *chipNAND 芯片描述符
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 *chipNAND 芯片对象
loff_t to要写入的偏移量
struct mtd_oob_ops *opsoob 操作描述结构
描述
使用 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 *mtdMTD设备结构
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 *mtdMTD设备结构
loff_t to要写入的偏移量
struct mtd_oob_ops *opsoob操作描述结构
-
int nand_erase(struct mtd_info *mtd, struct erase_info *instr)¶
[MTD 接口] 擦除块
参数
struct mtd_info *mtdMTD设备结构
struct erase_info *instr擦除指令
描述
擦除一个或多个块。
参数
struct nand_chip *chipNAND 芯片对象
struct erase_info *instr擦除指令
int allowbbt允许擦除 bbt 区域
描述
擦除一个或多个块。
-
void nand_sync(struct mtd_info *mtd)¶
[MTD 接口] 同步
参数
struct mtd_info *mtdMTD设备结构
描述
同步实际上是一个等待芯片准备好的函数。
-
int nand_block_isbad(struct mtd_info *mtd, loff_t offs)¶
[MTD 接口] 检查偏移量处的块是否损坏
参数
struct mtd_info *mtdMTD设备结构
loff_t offs相对于 MTD 起始位置的偏移量
-
int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)¶
[MTD 接口] 将给定偏移量处的块标记为坏块
参数
struct mtd_info *mtdMTD设备结构
loff_t ofs相对于 MTD 起始位置的偏移量
-
int nand_suspend(struct mtd_info *mtd)¶
[MTD 接口] 挂起 NAND 闪存
参数
struct mtd_info *mtdMTD设备结构
描述
成功返回 0,否则返回负错误代码。
-
void nand_resume(struct mtd_info *mtd)¶
[MTD 接口] 恢复 NAND 闪存
参数
struct mtd_info *mtdMTD设备结构
-
void nand_shutdown(struct mtd_info *mtd)¶
[MTD 接口] 完成当前的 NAND 操作并阻止进一步的操作
参数
struct mtd_info *mtdMTD设备结构
-
int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)¶
[MTD 接口] 锁定 NAND 闪存
参数
struct mtd_info *mtdMTD设备结构
loff_t ofs偏移字节地址
uint64_t len要锁定的字节数(必须是块/页大小的倍数)
-
int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)¶
[MTD 接口] 解锁 NAND 闪存
参数
struct mtd_info *mtdMTD设备结构
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 *chipNAND 芯片对象
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 *chipNAND芯片信息结构
const struct nand_ecc_caps *capsECC 容量信息结构
int oobavailECC引擎可以使用的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 *chipNAND芯片信息结构
const struct nand_ecc_caps *capsECC引擎能力信息结构
int oobavailECC引擎可以使用的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 *chipNAND芯片信息结构
const struct nand_ecc_caps *capsECC引擎能力信息结构
int oobavailECC引擎可以使用的OOB大小
描述
选择控制器上支持的并且可以容纳在芯片 OOB 中的最大 ECC 强度。 成功后,将设置所选的 ECC 设置。
参数
struct nand_chip *chipNAND 芯片对象
描述
这是普通 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 *thisNAND 芯片对象
uint8_t *buf临时缓冲区
int page起始页面
int num要读取的 bbt 描述符的数量
struct nand_bbt_descr *tdbbt 描述表
int offs表中块号偏移量
描述
从页面开始读取坏块表。
-
int read_abs_bbt(struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td, int chip)¶
[通用] 从给定页面开始读取坏块表
参数
struct nand_chip *thisNAND 芯片对象
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 *thisNAND 芯片对象
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 *thisNAND 芯片对象
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 *thisNAND 芯片对象
uint8_t *buf临时缓冲区
struct nand_bbt_descr *bd好/坏块搜索模式的描述符
int chip为特定芯片创建表,-1 读取所有芯片; 仅当设置了 NAND_BBT_PERCHIP 选项时适用
描述
通过扫描设备以寻找给定的好/坏块识别模式来创建坏块表。
参数
struct nand_chip *thisNAND 芯片对象
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 *thisNAND 芯片对象
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 *thisNAND 设备
struct nand_bbt_descr *tdBBT 描述
struct nand_bbt_descr *md镜像 BBT 描述符
int chipCHIP 选择器
描述
此函数返回一个正块号,指向适合存储 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 *thisNAND 设备
struct nand_bbt_descr *tdBBT 描述
int chipCHIP 选择器
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 *thisNAND 芯片对象
uint8_t *buf临时缓冲区
struct nand_bbt_descr *td坏块表的描述符
struct nand_bbt_descr *md坏块表镜像的描述符
int chipsel特定芯片的选择器,-1 表示全部
描述
(重新)写入坏块表。
参数
struct nand_chip *thisNAND 芯片对象
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 *thisNAND 设备
uint8_t *buf临时缓冲区
struct nand_bbt_descr *bd好/坏块搜索模式的描述符
描述
该函数检查先前调用 read_bbt 的结果,并在必要时创建/更新 bbt。 如果没有找到芯片/设备的 bbt,则需要创建。 如果缺少一个表或一个表的版本号小于另一个表,则需要更新。
参数
struct nand_chip *thisNAND 设备
loff_t offs新标记的块的偏移量
描述
该函数更新坏块表。
参数
struct nand_chip *thisNAND 设备
struct nand_bbt_descr *td坏块表描述符
描述
坏块表区域被标记为“坏”以防止意外擦除/写入。 这些区域由标记 0x02 标识。
参数
struct nand_chip *thisNAND 设备
struct nand_bbt_descr *bd要验证的表
描述
此函数对坏块描述表执行一些健全性检查。
参数
struct nand_chip *thisNAND 设备
struct nand_bbt_descr *bd好/坏块搜索模式的描述符
描述
该函数检查是否已存在坏块表。 如果没有,它会扫描设备以查找制造商标记的好/坏块,并将坏块表写入选定的位置。
坏块表内存在这里分配。 必须通过调用 nand_free_bbt 函数来释放它。
参数
struct nand_chip *this要为其创建描述符的 NAND 芯片
描述
此函数基于 **this** 的属性,分配并初始化一个用于 BBM 检测的 nand_bbt_descr。 新的描述符存储在 this->badblock_pattern 中。 因此,传递给此函数时,this->badblock_pattern 应为 NULL。
参数
struct nand_chip *thisNAND 芯片对象
loff_t offs设备中的偏移量
参数
struct nand_chip *thisNAND 芯片对象
loff_t offs设备中的偏移量
int allowbbt允许访问坏块表区域
参数
struct nand_chip *thisNAND 芯片对象
loff_t offs坏块的偏移量
致谢¶
以下人员为 NAND 驱动程序做出了贡献
Steven J. Hillsjhill@realitydiluted.com
David Woodhousedwmw2@infradead.org
Thomas Gleixnertglx@linutronix.de
许多用户提供了错误修复,改进和帮助进行测试。非常感谢。
以下人员为本文档做出了贡献
Thomas Gleixnertglx@linutronix.de