inkfish321 发表于 2011-4-29 14:45:57

IMX233添加新的FLASH驱动遇到问题。。

目前我在偿试往IMX233平台上增加新的NADN FLASH驱动,支持K9GAG08U0E。

由于K9GAG08U0E的PAGE SIZE是8K,而233的ECC加速器只支持一次处理4K的数据编码,或解码。

而且也不支持24位的ECC校验。



所以我修改了数据缓冲区大小

#define NAND_MAX_OOBSIZE        (436 * NAND_MAX_CHIPS)

#define NAND_MAX_PAGESIZE        (8192 * NAND_MAX_CHIPS)



同时修改了GPMI底层位于gpmi-nfc-hal-v0.c的两个函数,

static int read_page(struct gpmi_nfc_data *this, unsigned chip,dma_addr_t payload, dma_addr_t auxiliary)

static int send_page(struct gpmi_nfc_data *this, unsigned chip,dma_addr_t payload, dma_addr_t auxiliary)

将这个两函数改成:对于8K PAGE SIZE的FLASH读写操作分成两次4K的数据读写。使得命令的执行过程变成如下:

页读命令+地址--ECC读4K数据+ECC读4K数据--等待就绪

页写命令+地址--ECC写4K数据+ECC写4K数据--执行页写入命令--读状态字
其中 read_page_4k、 send_page_4k 是由原来的页读写函数修改而来,只是DMA读写的数据长度由current_page_size传递

http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_635209INZRIJ.png
(原文件名:11.png)

http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_635210EVWANA.png
(原文件名:12.png)

为了确保ECC仍然是16位模式我修改了

gpmi-nfc-hal-common.cint gpmi_nfc_set_geometry(struct gpmi_nfc_data *this)
gpmi-nfc-hal-v0.c static int set_geometry(struct gpmi_nfc_data *this)类似于如下形式:(选中高亮的部分为新增加的代码)

http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_635211SBY5ZK.png
(原文件名:13.png)
类似的 gpmi_nfc_set_geometry函数也做了相应的调整 。


然后增加新的FLASH器件信息,修改了

nand_device_info.c

static struct nand_device_info
nand_device_info_table_type_15[]

增加如下信息:
http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_635212ATR3RC.png
(原文件名:14.png)

同时修改了nand_base.c
static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                                                  struct nand_chip *chip, int busw, int *maf_id)

经过以上修改后,使用Manufacturing Tool MfgTool.exe下载编译后的文件,可以看到程序顺利执行完成下载动作。并且如果打开MTD DEBUG选项,可以看到往FLASH里写数据返回状态字0XE0,FLASH器件返回写入成功。
(MfgTool.exe这个工具是先将LINUX内核通过USB下载到板上的RAM,然后跳转执行,再利用内核对NAND FLASH驱动支持,将数据下载到NAND FLASH中。)

但是重启后并没有执行,现在我怀疑NAND FLASH驱动逻辑虽然正确,但可能是由于时序的差异造成读写数据不正确。于是我继续跟踪代码。找到位于
gpmi-nfc-hal-v0.c

static int set_timing(struct gpmi_nfc_data *this,const struct gpmi_nfc_timing *timing)

{
        struct nfc_hal*nfc = this->nfc;

        /* Accept the new timing. */
        nfc->timing = *timing;      
       
   /* Return success. */
        return 0;
}

发现这个函数只是简单的将nfc->timing这个指针指向参数timing所指向的地址,并没有使用这些参数具体的设置GPMI相关的寄存器。

我现在不明白为什么原来的BSP只做到这一步,是不是由于所有的对NAND FLASH操作都是通过等待ready/busy信号来判断操作是否完成,所以不需要去设置这些?

但是我想应该还是要设置的吧。

但接下去我要补充这部分代码我就需要知道GPMI_CLK的设置是多少,于是我根据这张图去寻找:
http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_635214PGJVSS.png
(原文件名:Screenshot-1.png)
最后找到位于linux-2.6.31/arch/arm/plat-stmp3xxx/clock.c 对于GPMI时钟设定相关的地方:

static struct clk_lookup onchip_clks[] = {
       ….....
      {
                .con_id = "pll",
                .clk = &pll_clk,
        },
      …........
      ….......
      {
                .con_id = "gpmi",
                .clk = &gpmi_clk,
        },
      …....
}

static struct clk pll_clk = {
        .parent                = &osc_24M,
        .enable_reg        = REGS_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0,
        .enable_shift        = 16,
        .enable_wait        = 10,
        .flags                = FIXED_RATE | ENABLED,
        .rate                = 480000,
        .ops                = &min_ops,
};

static struct clk gpmi_clk = {
        .parent                = &io_clk,
        .scale_reg        = REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI,
        .busy_reg        = REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI,
        .busy_bit        = 29,
        .enable_reg        = REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI,
        .enable_shift        = 31,
        .enable_negate        = 1,
        .bypass_reg        = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
        .bypass_shift        = 4,
        .flags                = NEEDS_SET_PARENT,
        .ops                = &std_ops,
};
它并没有像pll_clk那样子设置 .rate这个域。
我想知道它在哪设置了GPMI_CLK,还有为什么明明下载工具提示下载完成。可运行不起来。

lghtjpu 发表于 2011-4-29 14:51:03

LZ的问题好像已经纠结了有一段时间了,呵呵。
希望这里有大侠能帮到你了,帮顶!

inkfish321 发表于 2011-4-29 14:52:34

其实我想知道的是NAND FLASH写入的时候返回状态字0XE0,是不是还有可能写入失败。
而且这个失败是不是由于时序的问题?

258963519 发表于 2011-4-29 16:56:06

说下我的使用经历吧,一般来说状态字返回成功就是表明写入已经成功,除非是坏块,但是如果两块板子都是一模一样(注意,一模一样),就不是坏块的问题,是不是还有别的问题,比如说你写入的数据同读取的不一致(地址转换,数据指针之类的原因),应该不会有别的问题了

inkfish321 发表于 2011-4-29 18:17:42

static int set_timing(struct gpmi_nfc_data *this,
                                        const struct gpmi_nfc_timing *timing)
{
    struct device   *dev       =this->dev;
        struct nfc_hal*nfc = this->nfc;
        struct resources*resources = &this->resources;
        struct clk *clk = resources->clock;
       
        unsigned int gpmi_clk_rate = 0;
        unsigned int register_value = 0;

        /* Accept the new timing. */

        nfc->timing = *timing;

        gpmi_clk_rate = clk->get_rate(clk);      
      dev_info(dev, "%s gpmi_clk_rate = %d\r\n",__func__, gpmi_clk_rate);

...............
}

加入后面那两句返回来GPMI闪存控制器时钟周期是24MHZ,,对比一下FLASH数据手册,如果不用EDO模式
使用等待就绪模式基本不需要设置什么时序。
所以应该是其它问题。

inkfish321 发表于 2011-5-4 10:26:32

我今天用下载工具通过USB把内核和根文件系统烧到FLASH上;
然后重启,无法启运,之前就在怀疑芯片固化在ROM里的BOOT不支持新的FLASH的原因,所以不能启动。

于是早上我通过USB把内核直接解压到RAM,然后再由内核加载根文件系统,然后打印文件目录。
结果成功了。也能输出文件内容。
证明我的FLASH驱动没问题,能下载烧写程序。也能读出来。

现在就是ROM里的BOOT不知道该拿它怎么办了。

awakening 发表于 2011-5-25 22:48:13

可以用i2c的eeprom给boot打补丁,或者外面用spiflash放bootloader,设置233为spi flash启动,然后让bootloader去加载nand

inkfish321 发表于 2011-9-30 15:05:13

IMX233支持8K PAGE NAND FLASH问题已经全部解决了。国庆后会进行大批量测试,因为IMX233的SDK文件系统用的是UBIFS,程序改完后很容易发生位翻转的错误,对于NAND FLASH本身位翻转错误应该是由ECC纠错的。但UBIFS特殊的机制会在每次读取物理块时发现位翻转就进行块的搬移,物理块暴力测试等。最终会导至问题出现。
所以作出了一些修改。为了改这个问题把UBIFS过了一遍。

iedey 发表于 2012-10-23 15:55:30

inkfish321 发表于 2011-9-30 15:05 static/image/common/back.gif
IMX233支持8K PAGE NAND FLASH问题已经全部解决了。国庆后会进行大批量测试,因为IMX233的SDK文件系统用的 ...

最近也在搞imx233加8k page nand flash,可以分享一下你的是怎么解决的吗

abu0210 发表于 2012-11-24 10:00:37

看来楼主已经解决问题啦,mark一下!
页: [1]
查看完整版本: IMX233添加新的FLASH驱动遇到问题。。