1 Reply Latest reply on Mar 2, 2017 6:42 AM by fazh

    First partition is not erasing in the NOR flash S29GL064N (S29GL-N MirrorBit) 

    mallikarjun.bale

      Dear Sir/Madam,

                 I am using the Octeon CN66XX processor, with following detail's.

      we created three partition of the flash as uboot, cfpag and uboot-backup.
      For upgrading the uboot i want to erase first partition i.e. uboot and then
      copying new uboot binary to this partition. Problem is that first block in
      this partition is not getting erased. where all other partition are
      successfully erasing.


      1) Spansion Parallel NOR flash S29GL064N/ S29GL032N
      CFI conformant flash (16 x 16) Size: 8 MB in 135 Sectors
      AMD Standard command set

      2) Linux kernel 2.6.32.27

      3) processor - OCTEONCN66XX (mips)

      Details of the problem.


      1) we are making the partition for MTD flash by command line from u-boot as
      following
      "linux=linuxboot 0x20000000 0:3;bootoctlinux 0x20000000
      coremask=$(core_mask) isolcpus=2,3,4,5,6,7 mem=0xFF800000 root=/dev/msda1
      mtdparts=phys_mapped_flash:
      1024k(bootloader),1536k(fpga),1024k(ubootbackup)
      console=ttyS1,57600\0"

      2) in the log the partitions is created as

      Bootbus flash: Setting flash for 8MB flash at 0x1fc00000
      phys_mapped_flash: Found 1 x16 devices at 0x0 in 16-bit bank
      Amd/Fujitsu Extended Query Table at 0x0040
      phys_mapped_flash: Swapping erase regions for broken CFI table.
      number of CFI chips: 1
      cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
      3 cmdlinepart partitions found on MTD device phys_mapped_flash
      Creating 3 MTD partitions on "phys_mapped_flash":
      0x000000000000-0x000000100000 : "bootloader"
      0x000000100000-0x000000280000 : "fpga"
      0x000000280000-0x000000380000 : "ubootbackup"
       

         

      3) Linux shows the partitions as
      bash-4.0# cat /proc/mtd
      dev: size erasesize name
      mtd0: 00100000 00010000 "bootloader"
      mtd1: 00180000 00010000 "fpga"
      mtd2: 00100000 00010000 "ubootbackup"

      4) After giving command, flash_eraseall /dev/mtd2 and flash_eraseall /dev/mtd1

      are getting successfully erased
      , but when i erase mtd0 partition it gives
      the following error
      bash-4.0# flash_eraseall /dev/mtd0
      Erasing 64 Kibyte @ 0 -- 0 % complete.
      flash_eraseall: /dev/mtd0: MTD Erase failure: Input/output error
      Erasing 64 Kibyte @ f0000 -- 93 % complete.

      from error log observation is that the 1st block is not getting erased and
      remaining blocks are getting successfully erased in /dev/mtd0.


      5) I tried following method's to resolve this but not helped

      a) first i tried, making all the sectors of flash to un-protect in u-boot
      (by making changes in u-boot). Then boot Linux and tried to flash_eraseall
      /dev/mtd0.

      b) in file kernel_2.6/linux/arch/mips/cavium-octeon/octeon_68xx.dts.

         

      Removed the bootloader as ro (readonly)
      flash0: nor@0,0 {
      compatible = "cfi-flash";
      reg = <0 0 0x800000>;
      #address-cells = <1>;
      #size-cells = <1>;
      partition@0 {
      label = "bootloader";
      reg = <0 0x200000>;
      //read-only;
      };
      partition@200000 {
      label = "kernel";
      reg = <0x200000 0x200000>;
      };
      partition@400000 {
      label = "cramfs";
      reg = <0x400000 0x3fe000>;
      };
      partition@7fe000 {
      label = "environment";
      reg = <0x7fe000 0x2000>;
      //read-only;
      };
      };

      c) I cross checked for the each partition's mtd->flag it is
      MTD_CAP_NORFLASH (i.e. writable)

      d) i debugged
      the file linux/kernel_2.6/linux/drivers/mtd/chips/cfi_cmdset_0002.c. In this file
      after flash_eraseall /dev/mtd0
      in API - static int __xipram do_erase_oneblock(struct map_info *map, struct
      flchip *chip, unsigned long adr, int len, void *thunk)
      chip_good(map, adr, datum) is failed.

      e) before calling the do_erase_oneblock i invoked the API static int
      do_atmel_unlock(struct map_info *map, struct flchip *chip,
      unsigned long adr, int len, void *thunk);
      in @@ -1683,10 +1694,16 @@ static int cfi_amdstd_erase_varsize(struct
      mtd_info *mtd, struct erase_info *ins
      to unlock all the sectors in the block

         

      e) I introduced some delay before chip_good(map, adr, datum). For giving
      time to reflect the erase changes.

      d) the diff of cfi_cmdset_0002.c as follows

      --- a/OCTEON-SDK/linux/kernel_2.6/
      linux/drivers/mtd/chips/cfi_cmdset_0002.c
      +++ b/OCTEON-SDK/linux/kernel_2.6/linux/drivers/mtd/chips/cfi_cmdset_0002.c
      @@ -74,6 +74,9 @@ static void put_chip(struct map_info *map, struct flchip
      *chip, unsigned long ad
      static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
      static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);

      +static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
      + unsigned long adr, int len, void *thunk);
      +
      static struct mtd_chip_driver cfi_amdstd_chipdrv = {
      .probe = NULL, /* Not usable directly */
      .destroy = cfi_amdstd_destroy,
      @@ -1596,12 +1599,14 @@ static int __xipram do_erase_oneblock(struct
      map_info *map, struct flchip *chip,
      unsigned long timeo = jiffies + HZ;
      DECLARE_WAITQUEUE(wait, current);
      int ret = 0;
      -
      + printk(KERN_DEBUG "ENTERED in %s()",__func__);
      adr += chip->start;

      spin_lock(chip->mutex);
      ret = get_chip(map, chip, adr, FL_ERASING);
      if (ret) {
      +
      + printk(KERN_DEBUG "get_chip failed in %s() at line= 1607",__func__);
      spin_unlock(chip->mutex);
      return ret;
      }
      @@ -1663,11 +1668,17 @@ static int __xipram do_erase_oneblock(struct
      map_info *map, struct flchip *chip,
      /* Latency issues. Drop the lock, wait a while and retry */
      UDELAY(map, chip, adr, 1000000/HZ);
      }
      + /* MTD debug */
      + printk(KERN_DEBUG "delay for chip good");
      + UDELAY(map, chip, adr, 1000000/HZ);
      + UDELAY(map, chip, adr, 1000000/HZ);
      /* Did we succeed? */
      if (!chip_good(map, adr, map_word_ff(map))) {
      /* reset on all failures. */
      map_write( map, CMD(0xF0), chip->start );
      /* FIXME - should have reset delay before continuing */
      +
      + printk(KERN_DEBUG "chip_good failed in %s() at line=1675",__func__);

      ret = -EIO;
      }
      @@ -1683,10 +1694,16 @@ static int cfi_amdstd_erase_varsize(
      struct mtd_info
      *mtd, struct erase_info *ins
      {
      unsigned long ofs, len;
      int ret;
      -
      + printk(KERN_ALERT "Entered in cfi_amdstd_erase_varsize\n");
      ofs = instr->addr;
      len = instr->len;
      -
      +
      + ret = cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL);
      + if(ret)
      + {
      + printk(KERN_ALERT "Failed to do_atmel_unlock with ret = %d \n",ret);
      + }
      + printk(KERN_ALERT "Success to do_atmel_unlock with ret = %d \n",ret);
      ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
      if (ret)
      return ret;
      @@ -1765,11 +1782,18 @@ static int do_atmel_unlock(struct map_info *map,
      struct flchip *chip,
      spin_lock(chip->mutex);
      ret = get_chip(map, chip, adr + chip->start, FL_UNLOCKING);
      if (ret)
      + {
      + printk(" %s(): get_chip failed ",
      + __func__);
      +
      goto out_unlock;
      - chip->state = FL_UNLOCKING;
      + }
      + chip->state = FL_UNLOCKING;

      DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
      __func__, adr, len);
      + printk("MTD %s(): LOCK 0x%08lx len %d\n",
      + __func__, adr, len);

      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
      cfi->device_type, NULL);

      Please help me to understand this problem and to resolve

         

      Thank you,
      MS
       

        • 1. Re: First partition is not erasing in the NOR flash S29GL064N (S29GL-N MirrorBit) 
          fazh

          Hi,

             

           

             

          Please check following items  in function do_erase_oneblock in cfi_cmdset_0002.c.

             

           

             

          1. Do you see software timeout warning in following code when failure happens?

             

            if (time_after(jiffies, timeo)) {
             xip_enable(map, chip, adr);
             printk(KERN_WARNING "MTD %s(): software timeout\n",
              __func__ );
             break;
            }
           

             

          2. In following if condition, please add map_read 3 times before map_write( map, CMD(0xF0), chip->start ); and print out read data.

             

           

             

           /* Did we succeed? */
           if (!chip_good(map, adr, map_word_ff(map))) {
            /* reset on all failures. */
            map_write( map, CMD(0xF0), chip->start );
            /* FIXME - should have reset delay before continuing */

             

            ret = -EIO;
           }

             

           

             

          3. Print out input variable adr and len at the beginning of do_erase_oneblock.

             

           

             

          Best Regards,

             

          Clement