Nand flash driver problem

Olivier ERIBON olivier.eribon at free.fr
Fri May 17 17:52:09 EDT 2002


Hello,

I tried to port MTD_CVS with linux 2.4.19pre1 to an Walnut board with a nand
flash memory Toshiba TC58V32 (my specific hardware driver test.c is
under-mentionned with a part of .config).

I have 2 problems in a first time.

Linux/PPC load: console=ttyS0,9600 console=tty0 root=/dev/nfs
nfsroot=172.16.26.45:/home/oeribon/targetfs nfsaddrs=11
Uncompressing Linux...done.
Now booting the kernel
<9>Calibrating delay loop... PCI: Probing PCI hardware
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
JFFS version 1.0, (C) 1999, 2000  Axis Communications AB
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ
SERIAL_PCI enabled
ttyS00 at 0xef600300 (irq = 0) is a 16550A
ttyS01 at 0xef600400 (irq = 1) is a 16550A
loop: loaded (max 8 devices)
NAND device: Manufacture ID: 0x98, Chip ID: 0xe5 (Toshiba TC58V32DC)
Creating 1 MTD partitions on "Toshiba TC58V32DC":
0x00000000-0x00400000 : "TEST flash p1"
mtd: Giving out device 0 to TEST flash p1
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP, IGMP
Reset ethernet interfaces
<9>eth0: PPC405 EMAC: link up, 10 Mbps Half Duplex, auto-negotiation
complete<9>eth0: PPC405 EMAC: MAC 00:04:ac:e3:1d
<9>IP-Config: Complete:<9>      device=eth0, addr=172.16.27.111,
mask=255.255.252.0, gw=172.16.24.1<9>     host=serd.
Looking up port of RPC 100003/2 on 172.16.26.45
Looking up port of RPC 100005/1 on 172.16.26.45
INIT: version 2.78 bootingemory: 72k init
Activating swap...
Checking all file systems...
Parallelizing fsck version 1.19 (13-Jul-2000)
Setting kernel variables.
Mounting local filesystems...
not mounted anything
Hostname: serdmq7111.

Setting the System Clock using the Hardware Clock as reference...
System Clock set. Local time: Tue Apr 14 21:19:25 UTC 1970

Cleaning: /tmp /var/lock /var/run.
Initializing random number generator... done.
Checking password and group files... done.
INIT: Entering runlevel: 2
Starting system log daemon: syslogd klogd.
Starting internet superserver: inetd.
Starting FTP server: wu-ftpd.
Starting periodic command scheduler: cron.

MontaVista Software's Hard Hat Linux 2.0

serdmq7111 login: root

[root at serdmq7111 /root]# cd /new_util/


#### FIRST PROBLEM ####

[root at serdmq7111 /new_util]# ./eraseall /dev/mtd0
Erased 4096 Kibyte @ 0 -- 100% complete.
[root at serdmq7111 /new_util]# od -x /dev/mtd0
0000000 ffff ffff ffff ffff ffff ffff ffff ffff
*
20000000
[root at serdmq7111 /new_util]# date
Tue Apr 14 21:23:27 UTC 1970
[root at serdmq7111 /new_util]# date > /dev/mtd0
[root at serdmq7111 /new_util]# od -x /dev/mtd0
0000000 5475 6520 4170 7220 3134 2032 313a 3233
0000020 3a32 3920 5554 4320 3139 3730 0aff ffff
0000040 ffff ffff ffff ffff ffff ffff ffff ffff
*
20000000
[root at serdmq7111 /new_util]# date
Tue Apr 14 21:23:40 UTC 1970
[root at serdmq7111 /new_util]# date > /dev/mtd0

************* Here no error, I am surprised !!!!! *************
Because the flash has been first writing  by a date and tried to be
re-writed by another different date without error message

[root at serdmq7111 /new_util]# od -x /dev/mtd0
0000000 5475 6520 4170 7220 3134 2032 313a 3233
0000020 3a30 3020 5554 4320 3139 3730 0aff ffff
0000040 ffff ffff ffff ffff ffff ffff ffff ffff
*
20000000


#### SECOND PROBLEM ####

[root at serdmq7111 /new_util]# ./eraseall /dev/mtd0
Erased 4096 Kibyte @ 0 -- 100% complete.
[root at serdmq7111 /new_util]# od -x /dev/mtd0
0000000 ffff ffff ffff ffff ffff ffff ffff ffff
*
20000000
[root at serdmq7111 /new_util]# mount -t jffs /dev/mtdblock0 /mnt/jffs
JFFS: Trying to mount device 1f:00.
JFFS: GC thread pid=141.
JFFS: Successfully mounted device 1f:00.
jffs_garbage_collect_thread(): Starting infinite loop.
thread_should_wake(): free=4194304, dirty=0, blocksize=8192.
[root at serdmq7111 /new_util]# df
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/root             31121854  19412401  11398235  64% /
/dev/mtdblock0            4064         0      4064   0% /mnt/jffs
[root at serdmq7111 /new_util]# ll /mnt/jffs
total 0
[root at serdmq7111 /new_util]# cp /kernel-doc-nano-HOWTO.txt /mnt/jffs
thread_should_wake(): free=4194216, dirty=0, blocksize=8192.
jffs_write_node(): setting version of kernel-doc-nano-HOWTO.txt to 2
thread_should_wake(): free=4190092, dirty=88, blocksize=8192.
jffs_write_node(): setting version of kernel-doc-nano-HOWTO.txt to 3
thread_should_wake(): free=4189944, dirty=88, blocksize=8192.
jffs_write_node(): setting version of kernel-doc-nano-HOWTO.txt to 4
thread_should_wake(): free=4189696, dirty=88, blocksize=8192.
[root at serdmq7111 /new_util]# df
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/root             31121854  19412432  11398204  64% /
/dev/mtdblock0            4064         8      4056   1% /mnt/jffs
[root at serdmq7111 /new_util]# ll /mnt/jffs
total 5
-r--r--r--    1 root     root         4255 Apr 14 21:30
kernel-doc-nano-HOWTO.txt
c-nano-HOWTO.txt /new_util]# diff /mnt/jffs/kernel-doc-nano-HOWTO.txt
/kernel-doc
1c1,11
<                                                          t
---
> kernel-doc nano-HOWTO
> =====================
>
> Many places in the source tree have extractable documentation in the
> form of block comments above functions.  The components of this system
> are:
>
> - scripts/kernel-doc
>
>   This is a perl script that hunts for the block comments and can mark
>   them up directly into DocBook, man, text, and HTML. (No, not
132c142,143
< !I<filename> is replaced by the                               PORT_SYMBOL.
---
> !I<filename> is replaced by the documentation for functions that are
> _not_ exported using EXPORT_SYMBOL.

************* Why these differences betxeen initial and copy file ? Could it
be due to an electrical problem with my test development board (Walnut with
Nand flash added (very experimental installation)) ?  *************

With Regards,
Thanks in advance

Olivier Eribon

###################### test.c ######################
/*
 *  drivers/mtd/nand/test.c
 *
 * $Id: test.c,v 0.1 2002 april 22
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  Overview:
 *   This is a device driver for the NAND flash device found on the
 *   walnut board which utilizes the Toshiba TC58V32AFT part. This is
 *   a 32Mibit (4MiB x 8 bits) NAND flash device.
 */

#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <linux/init.h>

/*
 * MTD structure for walnut board
 */
static struct mtd_info *test_mtd = NULL;

/*
 * Values specific to the WALNUT board (used with GP405 processor)
 */

#define TEST_FIO_BASE 0xF1000000 /* Address where flash is mapped */

#define GPIO0_OR        0xEF600700 /* GPIO Output */
#define GPIO0_TCR       0xEF600704 /* GPIO Three-State Control */
#define GPIO0_ODR       0xEF600718 /* GPIO Open Drain */
#define GPIO0_IR        0xEF60071C /* GPIO Input */

#define GPIO_CLE        0x00000008 /* GPIO_04 */
#define GPIO_ALE        0x00000020 /* GPIO_02 */
#define GPIO_NCE        0x00000002 /* GPIO_06 */
#define GPIO_RNB        0x00008000 /* GPIO_08 */

/*
 * Module stuff
 */

#ifdef MODULE
MODULE_PARM(test_fio_base, "i");
MODULE_PARM(test_gpio0_or, "i");

__setup("test_fio_base=",test_fio_base);
__setup("test_gpio0_or=",test_gpio0_or);
#endif

/*
 * Define partitions for flash device
 */
const static struct mtd_partition partition_info[] = {
 { name: "TEST flash p1",
   offset: 0,
   size: 4*1024*1024 }
};

#define NUM_PARTITIONS 1

void * test_fio_base;
void * remap_gpio0_or;
void * remap_gpio0_tcr;
void * remap_gpio0_odr;
void * remap_gpio0_ir;

/*
 * hardware specific access to control-lines
 */
void test_hwcontrol(int cmd){
    unsigned long reg;

    asm (" sync");
    reg = readl (remap_gpio0_or);
    switch(cmd){
 case NAND_CTL_SETCLE:
   // CLE  1
          reg |= GPIO_CLE;
   break;
 case NAND_CTL_CLRCLE:
   // CLE  0
          reg &= ~GPIO_CLE;
   break;
 case NAND_CTL_SETALE:
          // ALE   1
          reg |= GPIO_ALE;
   break;
 case NAND_CTL_CLRALE:
          // ALE  0
          reg &= ~GPIO_ALE;
   break;
 case NAND_CTL_SETNCE:
   // CE   1
   reg &= ~GPIO_NCE;
   break;
 case NAND_CTL_CLRNCE:
          // CE  0
   reg |= GPIO_NCE;
   break;
    }
    writel (reg, remap_gpio0_or);
}

int board_pre_init (void)
{
    unsigned long reg;

    reg = readl (remap_gpio0_odr);
    reg &= ~0x0000002A;
    writel (reg, remap_gpio0_odr);

    reg = readl (remap_gpio0_tcr);
    reg |= 0x0000002A;
    writel (reg, remap_gpio0_tcr);

    reg = readl (remap_gpio0_or);
    reg &= (~0x00000028);
    reg |= 0x000000002;

    writel (reg, remap_gpio0_or);

    printk("<1>{board_pre_init} end\n");
    return 0;
}

/*
 * read device ready pin
 */
int test_device_ready(void)
{
    unsigned long reg;

    reg = readl (remap_gpio0_ir);
    if( (reg & GPIO_RNB) == (GPIO_RNB) ) {
     return 1;
    } else {
     return 0;
    }
}

/*
 * Main initialization routine
 */
int __init test_init (void)
{
 struct nand_chip *this;

 test_fio_base = ioremap(TEST_FIO_BASE, 0x00000010);
 if(!test_fio_base) {
  printk(KERN_ERR "TEST driver : ioremap (test_fio_base) failed \n");
  return (1);
 }

 remap_gpio0_or = ioremap(GPIO0_OR, 0x00000010);
 if(!remap_gpio0_or) {
  printk(KERN_ERR "TEST driver : ioremap (gpio0_or) failed \n");
  return (1);
 }

 remap_gpio0_tcr = ioremap(GPIO0_TCR, 0x00000010);
 if(!remap_gpio0_tcr) {
  printk(KERN_ERR "TEST driver : ioremap (gpio0_tcr) failed \n");
  return (1);
 }

 remap_gpio0_odr = ioremap(GPIO0_ODR, 0x00000010);
 if(!remap_gpio0_odr) {
  printk(KERN_ERR "TEST driver : ioremap (gpio0_odr) failed \n");
  return (1);
 }

 remap_gpio0_ir = ioremap(GPIO0_IR, 0x00000010);
 if(!remap_gpio0_ir) {
  printk(KERN_ERR "TEST driver : ioremap (gpio0_ir) failed \n");
  return (1);
 }

 /* Allocate memory for MTD device structure and private data */
 test_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
    GFP_KERNEL);
 if (!test_mtd) {
  printk ("Unable to allocate TEST NAND MTD device structure.\n");
  return -ENOMEM;
 }

 /* Get pointer to private data */
 this = (struct nand_chip *) (&test_mtd[1]);

 /* Initialize structures */
 memset((char *) test_mtd, 0, sizeof(struct mtd_info));
 memset((char *) this, 0, sizeof(struct nand_chip));

 /* Link the private data with the MTD structure */
 test_mtd->priv = (void*)this;

 /* Set address of NAND IO lines */
 this->IO_ADDR_R = (unsigned long)test_fio_base;
 this->IO_ADDR_W = (unsigned long)test_fio_base;
 /* Set address of hardware control function */
 this->hwcontrol = test_hwcontrol;
 this->dev_ready = test_device_ready;
 /* 20 us command delay time */
 this->chip_delay = 30;

 /*
  * Set GPIO Port E control register so that the pins are configured
  * to be outputs for controlling the NAND flash.
  */
 board_pre_init(); /* between  Link the ... and Set address of ... */

 /* Scan to find existence of the device */
  if (nand_scan (test_mtd)) {
  kfree (test_mtd);
  printk ("Unable Scan to find existence of the device\n");
  return -ENXIO;
 }

 /* Allocate memory for internal data buffer */
 this->data_buf = kmalloc (sizeof(u_char) * (test_mtd->oobblock +
test_mtd->oobsize), GFP_KERNEL);
 if (!this->data_buf) {
  printk ("Unable to allocate NAND data buffer for TEST.\n");
  kfree (test_mtd);
  return -ENOMEM;
 }

 /* Allocate memory for internal data buffer */
 this->data_cache = kmalloc (sizeof(u_char) * (test_mtd->oobblock +
test_mtd->oobsize), GFP_KERNEL);
 if (!this->data_cache) {
  printk ("Unable to allocate NAND data cache for TEST.\n");
  kfree (this->data_buf);
  kfree (test_mtd);
  return -ENOMEM;
 }
 this->cache_page = -1;

 /* Register the partitions */
 add_mtd_partitions(test_mtd, partition_info, (int)NUM_PARTITIONS);

 /* Return happy */
 return 0;
}
module_init(test_init);

/*
 * Clean up routine
 */
#ifdef MODULE
static void __exit test_cleanup (void)
{
 struct nand_chip *this = (struct nand_chip *) &test_mtd[1];

 /* Unregister the device */
 del_mtd_device (test_mtd);

 /* Free internal data buffer */
 kfree (this->data_buf);
 kfree (this->data_cache);
 /* Free the MTD device structure */
 kfree (test_mtd);
}
module_exit(test_cleanup);
#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Steven J. Hill <sjhill at cotw.com");
MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on SPIA
board");

###################### .config ######################

#
# Platform support
#
CONFIG_PPC=y
CONFIG_PPC32=y
# CONFIG_6xx is not set
CONFIG_4xx=y
# CONFIG_POWER3 is not set
# CONFIG_8xx is not set
# CONFIG_PPC_ISERIES is not set
# CONFIG_PPC_STD_MMU is not set
# CONFIG_ASH is not set
# CONFIG_CEDER is not set
# CONFIG_CPCI405 is not set
# CONFIG_EP405 is not set
# CONFIG_PIP405 is not set
# CONFIG_MIP405 is not set
# CONFIG_OAK is not set
# CONFIG_REDWOOD_4 is not set
# CONFIG_REDWOOD_5 is not set
# CONFIG_TIVO is not set
CONFIG_WALNUT=y
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
# CONFIG_MATH_EMULATION is not set
CONFIG_405GP=y
CONFIG_BIOS_FIXUP=y
CONFIG_TREEBOOT=y
CONFIG_IBM405_ERR77=y
CONFIG_IBM_OCP=y
# CONFIG_405_DMA is not set
# CONFIG_PM is not set
# CONFIG_OCP_PROC is not set
CONFIG_UART0_TTYS0=y
# CONFIG_UART0_TTYS1 is not set
CONFIG_IBM405_ERR51=y
CONFIG_NOT_COHERENT_CACHE=y

#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=0
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
#
# NAND Flash Device Drivers
#
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC=y
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
CONFIG_MTD_NAND_TEST=y                      <=   Key for my test driver

#
# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_ADFS_FS is not set
# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_JBD is not set
# CONFIG_JBD_DEBUG is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_JFFS_FS=y
CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_JFFS_PROC_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_TMPFS=y
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
# CONFIG_UDF_FS is not set
# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
# CONFIG_UFS_FS_WRITE is






More information about the linux-mtd mailing list