⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jnand.c.bak

📁 QUALCOMM JNAND DRIVER
💻 BAK
📖 第 1 页 / 共 4 页
字号:


/*===========================================================================

FUNCTION flash_initialize_boot

DESCRIPTION
  This function calls the flash probe function and sets up everything to be
  ready to erase and program the device.

DEPENDENCIES
  Assumes jtag_flash_param (global variable) has valid parameters.

RETURN VALUE
  If success, return FLASH_SUCCESS else FLASH_FAIL

SIDE EFFECTS

===========================================================================*/

uint32 
flash_initialize_boot()
{
  KICK_WATCHDOG();

  DPRINTF (("\n\n------ Boot Initialize ----------------------\n"));

  DPRINTF (("Probing flash device:  "));

  nand_device=fs_nand_device_probe();

  if ( nand_device == (struct fs_device_data *)FS_NO_DEVICE)
  {
    DPRINTF (("Error: no nand_device found \n"));
    SET_ERR (ERR_DEV_MISSING);
    return FLASH_FAIL;
  }

  /* Initialize the CRC with the seed value so we only have to
   * call the step function.  This must be done initialize, not
   * just at compile time with an assignment on the variable
   * declaration, because we call this program multiple times
   * and during EACH invocation run, we must start the CRC
   * over from the seed. */
  crc = CRC_30_STEP_SEED;

  /* get some information about the device */
  block_count = nand_device->block_count(nand_device);
  pages_in_block = nand_device->block_size(nand_device);
  page_size = nand_device->page_size(nand_device);
  flash_name = nand_device->device_name(nand_device);

  /* calculate size of eraseable unit and max number of pages */
  eu_size = pages_in_block * page_size;
  max_pages = block_count * pages_in_block;

  /* page counter later used to read back image for verification */
  boot_block_pages = 0;

  boot_block_mode = TRUE;

  DPRINTF (("Found %s\n", flash_name));

#ifdef DEBUG_LOGIC
#error code not present
#endif

  KICK_WATCHDOG();

  /* Init some things that must be re-inited on every invocation.  */
  start_addr_loaded = FALSE;
  
  image_size = 0;
  input_gap_size = 0;
  bad_block_gap_size = 0;
  partial_page_index = 0;

  current_block = 0;
  avail_pages_in_block = 0;
  current_page = 0;
  
  
  KICK_WATCHDOG();

  return FLASH_SUCCESS;

} // flash_initialize_boot



/*===========================================================================

FUNCTION flash_erase

DESCRIPTION
  This function does nothing.  It is just a stub.  Since we only require
  that block 0 be good, and we can work around any other bad blocks for
  the Boot Information Block and the image data, there is no longer
  anything to do.
  
DEPENDENCIES
  None

RETURN VALUE
  Always return FLASH_SUCCESS

SIDE EFFECTS

===========================================================================*/

uint32 flash_erase()
{
  return FLASH_SUCCESS;
}  // flash_erase

/*===========================================================================

FUNCTION flash_erase_boot

DESCRIPTION
  This function checks the boot block only, then erases it
  
DEPENDENCIES

RETURN VALUE
  If block 0 is good return FLASH_SUCCESS
  If block 0 is bad return  FLASH_FAIL

SIDE EFFECTS

===========================================================================*/

uint32 flash_erase_boot()
{
  int i = 0; 

  DPRINTF (("\n------ ERASE BOOT -----\n"));


  /* For right now, only check block 0, leaving other blocks
   * alone.  If this block is bad, we fail utterly  */

  KICK_WATCHDOG();
  if (nand_device->bad_block_check(nand_device, i) == 
      FS_DEVICE_BAD_BLOCK)
  {
    TPRINTF (0, ("flash_erase:  bad block %d\n", i));
    return FLASH_FAIL;
  }
  KICK_WATCHDOG();
  
  /* erase the block */
  if (nand_device->erase_block(nand_device, i) != FS_DEVICE_DONE)
  {
    DPRINTF (("Error: device failed during erase of block %d\n", i));
    SET_ERR (ERR_ERASE_FAIL);
    return FLASH_FAIL;
  }
  KICK_WATCHDOG();

  /* We do this here instead of in initialize because until we have
   * erased this block successfully, we have none.  Now we do, and 
   * because we are in boot_block_mode, we will never call
   * prepare_next_block() which would normally erase and init the
   * first block. */
  avail_pages_in_block = page_size;

  return FLASH_SUCCESS;

}  // flash_boot




/*===========================================================================

FUNCTION flash_program

DESCRIPTION
  This function will write the flash.  It gets invoked every time the
  JTAG ICD has filled a buffer.  Those buffer fills may not have any
  correspondence to the size of the pages we can write to the flash,
  so we must be prepared to partially fill a block with data on one pass
  through and then continue filling the block on the next pass through.
  This means that state must be maintained in globals after this function
  has finished with the current invocation.

DEPENDENCIES
  Assumes jtag_flash_param (global variable) has valid parameters.

RETURN VALUE
  If success, return FLASH_SUCCESS else FLASH_FAIL

SIDE EFFECTS

===========================================================================*/

uint32 flash_program()
{
  byte *data;
  dword addr;
  word  size;
  unsigned int fill_remaining_in_page;

  unsigned int partial_bytes_avail, num_fill_bytes;
  unsigned int gap_size;
  unsigned int new_last_code_addr;
  unsigned char *wbuf;

  KICK_WATCHDOG();

  // DPRINTF (("\n----- PROGRAM ------\n"));

  data = jtag_flash_param.data + jtag_flash_param.offset;
  addr = jtag_flash_param.addr + jtag_flash_param.offset
         - jtag_flash_param.flashaddr;
  size = jtag_flash_param.size;


  /* Save address of last code byte so we know where the next block of 
   * code is in relation to it's predecessor.
   */
  new_last_code_addr = addr + size;

  /* If this is the first block of code, save the start address 
   * of the code image in the RAM copy of BIB. */
  if (start_addr_loaded == FALSE)
  {
    start_addr_loaded = TRUE;
    bib1.startaddr = addr;
    last_code_addr = addr;
  }

  /* If there is a gap between previous last image address and the
   * starting address of the current image data, fill with fill char 
   * and update number of fill chars used.  Also, we are forced to
   * use the partial page buffer if we are doing a fill. Account for
   * gaps that stay within the partial page, as well as gaps that go
   * beyond the partial, and possibly gaps that are larger than the
   * the partial page.  However, we no longer have any spans to close out, 
   * so we just fill with required number of fill bytes and write out 
   * full pages as necessary, even if they are merely full of fill bytes. */
  KICK_WATCHDOG();
  if (last_code_addr != addr)
  {
    gap_size = num_fill_bytes = addr - last_code_addr;

  /* check to make sure we have not got a block with an address less
   * than we have had before.
   */
  if (addr < last_code_addr)
  {
    DPRINTF (("Error: addr to program %d < previous addr %d \n",
              addr, last_code_addr));
    SET_ERR (ERR_ADDR_REVERSE);
    return FLASH_FAIL;
  }
    
    while (num_fill_bytes > 0)
    {
      partial_bytes_avail = page_size - partial_page_index;
      fill_remaining_in_page = MIN (partial_bytes_avail, num_fill_bytes);
      while (fill_remaining_in_page > 0)
      {
        partial_page_buffer[partial_page_index++] = 
          (unsigned char)NAND_FILL_CHAR;
        num_fill_bytes--;
        fill_remaining_in_page--;
      }
      if (partial_page_index > page_size)
      {
        SET_ERR (ERR_PPI_TOO_BIG);
        return FLASH_FAIL;
      }
      if (partial_page_index == page_size)
      {
        KICK_WATCHDOG();
        if ((write_partial_page (addr, UPDATE_CRC)) == FALSE)
        {
          return FLASH_FAIL;
        }
        partial_page_index = 0;
      
      } /* partial page is full */
    } /* while */ 
    
    input_gap_size += gap_size;
  } /* there is a gap in code addresses */
  
  KICK_WATCHDOG();

  /* Now write the data */

  while (size > 0)
  {
    partial_bytes_avail = page_size - partial_page_index;

    if (partial_bytes_avail > size)
    {
      /* fill partial page partially and we are done, do not write page,
       * no need to update data ptr as we are out of data */
      memcpy(&partial_page_buffer[partial_page_index], data, size);
      partial_page_index += size;
      break;
    }
    else if ((partial_bytes_avail == size) && (partial_page_index != 0))
    {
      /* fill partial page completely, ready for writing, none left over */
      memcpy(&partial_page_buffer[partial_page_index], data, size);
      wbuf = partial_page_buffer;
      data += partial_bytes_avail;
      size -= partial_bytes_avail;
      partial_page_index = 0;
    }
    else if ((partial_bytes_avail < size) && (partial_page_index != 0))
    {
      /* fill partial page completely, ready for writing, some left over */
      memcpy(&partial_page_buffer[partial_page_index], data, partial_bytes_avail);
      wbuf = partial_page_buffer;
      data += partial_bytes_avail;
      size -= partial_bytes_avail;
      partial_page_index = 0;
    }
    else /* partial_page_index == 0 && size >= page_size */
    {
      /* write a full page from where it is */
      wbuf = data;
      data += page_size;
      size -= page_size;
    }
    
    KICK_WATCHDOG();

    /* Write a full page.  If we do not break out of the while early,
     * and we reach here, there is a full page to be written. */
    if (write_current_page (wbuf, addr, UPDATE_CRC) == FALSE)
    {
      return FLASH_FAIL;
    }
    KICK_WATCHDOG();

    /* We only get here when we have a full page to write, so the
     * increment of the address in the code image is always by a page. */
    addr += page_size;
  }

  /* Save the RAM address of the last byte of the image written, so
   * that when we get called next, we can see if there are any gaps */
  last_code_addr = new_last_code_addr;
  
  if (partial_page_index > page_size)
  {
    return FLASH_FAIL;
  }
  
  return FLASH_SUCCESS;

} // flash_program


/*===========================================================================

FUNCTION flash_program_boot

DESCRIPTION
  This function will write the flash.  It gets invoked every time the
  JTAG ICD has filled a buffer.  Those buffer fills may not have any
  correspondence to the size of the pages we can write to the flash,
  so we must be prepared to partially fill a block with data on one pass
  through and then continue filling the block on the next pass through.
  This means that state must be maintained in globals after this function
  has finished with the current invocation.

DEPENDENCIES
  Assumes jtag_flash_param (global variable) has valid parameters.

RETURN VALUE
  If success, return FLASH_SUCCESS else FLASH_FAIL

SIDE EFFECTS

===========================================================================*/

uint32 flash_program_boot()
{
  byte *data;
  dword addr;
  word  size;
  unsigned int partial_bytes_avail, num_fill_bytes, fill_remaining_in_page;
  unsigned int gap_size;
  unsigned int new_last_code_addr;
  unsigned char *wbuf;

  KICK_WATCHDOG();

  DPRINTF (("\n----- PROGRAM BOOT BLOCK------\n"));

  data = jtag_flash_param.data + jtag_flash_param.offset;
  addr = jtag_flash_param.addr + jtag_flash_param.offset
         - jtag_flash_param.flashaddr;
  size = jtag_flash_param.size;

  /* Save address of last code byte so we know where the next block of 
   * code is in relation to it's predecessor.
   */
  new_last_code_addr = addr + size;

  /* If this is the first block of code, save the start address 
   * of the code image */
  if (start_addr_loaded == FALSE)
  {
    start_addr_loaded = TRUE;
    last_code_addr = addr;
  }

  /* If there is a gap between previous last image address and the
   * starting address of the current image data, fill with fill char 
   * and update number of fill chars used.  Also, we are forced to
   * use the partial page buffer if we are doing a fill. Account for
   * gaps that stay within the partial page, as well as gaps that go
   * beyond the partial, and possibly gaps that are larger than the
   * the partial page.  However, as opposed to regular programming
   * mode, we do not have any spans to close out, so we just
   * fill with required number of fill bytes and write out full pages
   * as necessary, even if they are merely full of fill bytes. */
  KICK_WATCHDOG();
  if (last_code_addr != addr)
  {
    gap_size = num_fill_bytes = addr - last_code_addr;

  /* check to make sure we have not got a block with an address less
   * than we have had before.
   */
  if (addr < last_code_addr)
  {
    DPRINTF (("Error: addr to program %d < previous addr %d \n",
              addr, last_code_addr));
    SET_ERR (ERR_ADDR_REVERSE);
    return FLASH_FAIL;
  }
    
    while (num_fill_bytes > 0)
    {
      partial_bytes_avail = page_size - partial_page_index;
      fill_remaining_in_page = MIN (partial_bytes_avail, num_fill_bytes);
      while (fill_remaining_in_page > 0)
      {
        partial_page_buffer[partial_page_index++] = 
          (unsigned char)NAND_FILL_CHAR;
        num_fill_bytes--;
        fill_remaining_in_page--;
      }
      if (partial_page_index > page_size)
      {
        SET_ERR (ERR_PPI_TOO_BIG);
        return FLASH_FAIL;
      }
      if (partial_page_index == page_size)
      {
        KICK_WATCHDOG();
        if ((write_partial_page (addr, UPDATE_CRC)) == FALSE)
        {
          return FLASH_FAIL;
        }
        partial_page_index = 0;
      } /* partial page is full */
    } /* while */ 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -