问题: kernel 启动后,运行到下面行挂起。
[42949373.810000] nx_2016: Found 1 x16 devices at 0x0 in 16-bit bank
[42949373.820000]  Intel/Sharp Extended Query Table at 0x0035
[42949373.820000] Using buffer write method
[42949373.830000] cfi_cmdset_0001: Erase suspend on write enabled
[42949373.830000] Creating 0 MTD partitions on "nx_2016":
[42949373.840000] NAND device: Manufacturer ID: 0x20, Chip ID: 0x76 (ST Micro NAND 64MiB 3,3V 8-bit)


挂起的函数调用层次关系:
-------------------------------------------------------------------------------------------------------------------------------------------
module_init(nx_nand_init)
nx_nand_init(){
   nx_nand_driver.probe = nx_nand_probe;
   platform_driver_register(nx_nand_driver)
}
=>
nx_nand_probe()
=>
nand_scan_tail()
=>
nand_default_bbt()  //Select a default bad block table for the device
=>
nand_scan_bbt() //scan, find, read and maybe create bad block table(s)
=>
search_read_bbts() //scan the device for bad block table(s)
=>
search_bbt() //scan the device for a specific bad block table
=>
scan_read_raw() //Scan read raw data from flash
=>
nand_read_oob() //NAND read data and/or out-of-band
=>
nand_do_read_ops() //Read data with ECC
=>
nx_nand_command(NAND_CMD_READ0) //Command function for small page chips
=>
tmhwEfmc_SetDmaConfig() //This function will setup the DMA configuration for the data transfer to/from NAND flash devices connected the EFMC.
=>
TMVH_GEN_WRITE( regs, regVal );
-------------------------------------------------------------------------------------------------------------------------------------------
最后TMVH_GEN_WRITE()挂起,问题应该是和Nand有关,据说是Nand坏?

检查u-boot里面的环境变量altflash为NAND,由运行过的命令"gcs sel NAND"产生,如果altflash设置为空,启动没有问题。

A. gcs学习
我们在u-boot下面运行#gcs info
*******************************
GCS Flash Info--
BOOT Device:--NOR Flash.
ALT Flash Device:--NAND Flash.
*******************************
其中,Boot Device通过RGU_CNFG_TRAPS_REG获取。
注:RGU_CNFG_TRAPS_REG
见<<ApolloUG>>,Reset Generation Unit(RGU)中的Chip Configuration Register。该寄存器在复位并稳定的过程中采样得到。

而ALT Flash Device,u-boot在初始化时读取$altflash获得,并且可以通过#gcs sel命令进行修改。


B. altflash设置为空,如何影响kernel启动?
nx_nand_probe()
=>
nand_scan_ident()
=>
nand_get_flash_type()
读取到的device id为0x50,匹配不到对应的device type,所以也不去scan bbt。

而,altflash为NAND时,
读取到的device_id为0x76,匹配到的device type为“NAND 64MiB 3,3V 8-bit”。

读取device_id的函数是,nx_nand_read_byte(),是通过Efmc完成,完全硬件实现。

为何有这种区别呢?
因为altflash设为NAND时,u-boot对该设备进行过初始化和命令的传递。而altflash为空时,u-boot没有对该设备进行访问。结果两种情况下得到的device_id不一致,且皆不正确---因为kernel对该设备的驱动有问题(?)。

C. 问题的解决
分析是驱动的问题,需要加载正确的驱动。
幸好上海同事已经有解决,拖过来分析如下:
arch/arm/mach-apollo/nand.c

arch_initcall(apollo_nand_init);

static int __init apollo_nand_init(void)
{
#if 1
    /**
     * FIXME: This configuration must come from bootloader
     **/
    void * __iomem base = ioremap(apollo_ip2017_resources[0].start,
            APOLLO_IP2017_LEN);
    if (base == NULL) {
        printk(KERN_ERR "NAND_DEVICE: out of memory?!\n");
        return -ENOMEM;
    }
    #if 0
    writel(0x014, base + 0x04C);
#ifdef CONFIG_EXECUTE_ON_EMULATOR
    writel(0x02644448, base + 0x050); /* Set timings */
    writel(0x00108444, base + 0x054);
#endif
#ifdef CONFIG_PCI
    writel(0x3FE, base + 0x010);
#else
    writel(0x3F, base + 0x010);
#endif
#endif
    iounmap(base);
#endif /* FIXME: Remove it once the bootloader is updated */
    return platform_device_register (&apollo_ip2017_device);
}

解决的关键是#if 0里面的处理。............. 缺少IP2017资料,将来有机会再理解吧。。。

D. mtdparts, bootargs, nandboot
gcs sel NAND
setenv bootcmd "dhcp; run nandboot;"
setenv uboot_cmdline 1
setenv mtdids "nand0=nx_2017,nor0=nx_2016"
setenv mtdparts "mtdparts=nx_2016:1536k(boot),-(extra);nx_2017:1536k(unused),5m(kernel),32m(root),32m(appfs),-(nandextra)"
save

setenv bootargs "noinitrd console=ttyS1,115200n8 $mtdparts root=/dev/mtdblock6 rw rootfstype=jffs2 ${extra}"
save


E. attach相关的uldr&u-boot
附上uldr和u-boot相关的改动。