关于如何配置Linux NAND flash driver,大家可以参考processors.wiki.ti.com/.../AM335x_NAND_Driver's_Guide
对于一些接触Linux NAND flash driver的朋友,这里简要介绍一下。
Linux下,访问NAND,NOR等flash,是通过MTD(Memory Technology Device)子系统进行的。使用MTD的目的在于为各种memory,尤其是flash的访问提供一个通用的接口。
从上述框图,可以看出MTD框架下的NAND FLASH驱动主要分为
MTD设备层
MTD原始设备层
Flash 硬件驱动层
关于MTD具体的实现感兴趣的,可以在网上找更多的资料参考。
在这里,我们主要讨论在AM335X系统设计中,进行NAND FLASH设计时,驱动侧需要修改哪些地方。
从上述部分可以看出,与硬件底层相关的部分为flash硬件驱动层。
由于Linux NAND驱动的日益标准化,NAND的底层操作大抵相同,在使用不同NAND flash时,需要修改的部分比较简单。
以SDK06.00为例,只需要修改如下部分:
(1)NAND pinmux配置:该部分进行NAND flash的管脚配置。如使用16-bit的NAND flash,需要在如下结构体中增加高8bit的管脚配置。
路径: linux\arch\arm\mach-omap2\board-am335xevm.c
/* Pin mux for nand flash module */
static struct pinmux_config nand_pin_mux[ ]
(2) NAND 分区信息配置:该部分决定NAND FLASH的分区情况,大致会分为SPL,SPL_BACKUP, U-BOOT, KERNEL, FILESYSTEM, USER_DATA
路径: linux\arch\arm\mach-omap2\board-am335xevm.c
/* NAND partition information */
static struct mtd_partition am335x_nand_partitions[]
(3) NAND 时序配置:针对不同的NAND flash型号,时序要求会有差异。AM335X通过GPMC与NAND连接,可通过配置GPMC的时序,达到正确快速地访问NAND flash中的数据。
路径: linux\arch\arm\mach-omap2\board-am335xevm.c
static struct gpmc_timings am335x_nand_timings
上述结构体统一在evm_nand_init()中调用:
static void evm_nand_init(int evm_id, int profile)
{
struct omap_nand_platform_data *pdata;
struct gpmc_devices_info gpmc_device[2] = {
{ NULL, 0 },
{ NULL, 0 },
};
setup_pin_mux(nand_pin_mux);
pdata = omap_nand_init(am335x_nand_partitions,
ARRAY_SIZE(am335x_nand_partitions), 0, 0,
&am335x_nand_timings);
if (!pdata)
return;
pdata->ecc_opt =OMAP_ECC_BCH8_CODE_HW; // 使用BCH8 ECC
pdata->elm_used = true;
gpmc_device[0].pdata = pdata;
gpmc_device[0].flag = GPMC_DEVICE_NAND;
omap_init_gpmc(gpmc_device, sizeof(gpmc_device));
omap_init_elm();
}
而evm_nand_init最终通过一个板级配置的结构体进行调用,如
static struct evm_dev_cfg gen_purp_evm_dev_cfg[] = {
{am335x_rtc_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{clkout2_enable, DEV_ON_BASEBOARD, PROFILE_ALL},
{enable_ecap0, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{lcdc_init, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{mfd_tscadc_init, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{rgmii1_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{rgmii2_init, DEV_ON_DGHTR_BRD, (PROFILE_1 | PROFILE_2 |
PROFILE_4 | PROFILE_6) },
{usb0_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{usb1_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{evm_nand_init, DEV_ON_DGHTR_BRD,
(PROFILE_ALL & ~PROFILE_2 & ~PROFILE_3)},
}
Note: 由于TI GPEVM板上使用一个拨盘开关进行切换,来实现不同的profile下的管脚复用。
如设计是直接连接,其后写PROFILE_ALL即可。
参考文档:
blog.csdn.net/.../6961406
