예제 #1
0
파일: mtd_onfi.c 프로젝트: a1ien/nuttx
bool onfi_ebidetect(uintptr_t cmdaddr, uintptr_t addraddr,
                    uintptr_t dataaddr)
{
  uint32_t timer;
  uint8_t rc;
  bool found = false;
  uint8_t ids[4];
  uint8_t i;

  finfo("cmdaddr=%08x addraddr=%08x dataaddr=%08x\n",
        (int)cmdaddr, (int)addraddr, (int)dataaddr);

  /* Send Reset command */

  WRITE_NAND_COMMAND(NAND_CMD_RESET, cmdaddr);

  /* If a Nandflash is connected, it should answer to a read status command */

  for (timer = 0; timer < 60; timer++)
    {
      rc = onfi_readstatus(cmdaddr, dataaddr);
      if (rc == OK)
        {
          WRITE_NAND_COMMAND(NAND_CMD_READID, cmdaddr);
          WRITE_NAND_ADDRESS(0, addraddr);

          ids[0] = READ_NAND(dataaddr);
          ids[1] = READ_NAND(dataaddr);
          ids[2] = READ_NAND(dataaddr);
          ids[3] = READ_NAND(dataaddr);

          for (i = 0; i < NAND_NMODELS ; i++)
            {
              if (g_nandmodels[i].devid == ids[1])
                {
                  found = true;
                  break;
                }
            }

          break;
        }
    }

  if (!found)
    {
      if (onfi_compatible(cmdaddr, addraddr, dataaddr))
        {
          /* Report true if it is an ONFI device that is not in device
           * list (perhaps it is a new device that is ONFI campatible
           */

          found = true;
       }
    }

  return found;
}
예제 #2
0
/**
 * \brief This function retrieves the data structure that describes the target¡®s 
 * organization, features, timings and other behavioral parameters.
 * \param pOnfiPageParameter Pointer to a PmeccDescriptor instance.
 * \return  0: ONFI not compliant or not supported.
            1: ONFI compliant
*/
uint8_t NandGetOnfiPageParam (OnfiPageParam *pOnfiPageParameter)
{
    uint8_t i;
    uint8_t rc;
    uint8_t onfi_param_table[ONFI_PARAM_TABLE_SIZE];

    if (NandIsOnficompatible()) {
        pCurrentOnfiPageParam = pOnfiPageParameter;
        pOnfiPageParameter->onfiCompatiable = 1;
        for (i = 0; i < ONFI_PARAM_TABLE_SIZE; i++) {
            onfi_param_table[i] = 0xFF;
        }
        /* Perform Read Parameter Page command */
        WRITE_NAND_COMMAND(NAND_CMD_READ_PARAM_PAGE, EBI_NF_ADDR);
        WRITE_NAND_ADDRESS(0x0, EBI_NF_ADDR);

        /* Wait NF ready */
        _NandReadStatus();
        /* Re-enable data output mode required after Read Status command */
        WRITE_NAND_COMMAND(NAND_CMD_READ0, EBI_NF_ADDR);

        /* Read the parameter table */
        for (i = 0; i < ONFI_PARAM_TABLE_SIZE; i++) {
            onfi_param_table[i] = READ_NAND(EBI_NF_ADDR);
        }
        for (i = 0; i < ONFI_PARAM_TABLE_SIZE; i++) {
            if ( onfi_param_table[i] != 0xFF ) break;
        }
        if ( i == ONFI_PARAM_TABLE_SIZE) {
            pOnfiPageParameter->onfiCompatiable = 0;
            return 0;
        }
        /* JEDEC manufacturer ID */
        pOnfiPageParameter->manufacturerId = *(uint8_t *)(onfi_param_table + 64);
        /* Bus width */
        pOnfiPageParameter->onfiBusWidth = (*(uint8_t *)(onfi_param_table + 6)) & 0x01;
        /* Get number of data bytes per page (bytes 80-83 in the param table) */
        pOnfiPageParameter->onfiPageSize =  *(uint32_t *)(void*)(onfi_param_table + 80);
        /* Get number of spare bytes per page (bytes 84-85 in the param table) */
        pOnfiPageParameter->onfiSpareSize =  *(uint16_t *)(void*)(onfi_param_table + 84);
        /* Number of pages per block. */
        pOnfiPageParameter->onfiPagesPerBlock = *(uint32_t *)(void*)(onfi_param_table + 92);
        /* Number of blocks per logical unit (LUN). */
        pOnfiPageParameter->onfiBlocksPerLun = *(uint32_t *)(void*)(onfi_param_table + 96);
        /* Number of logical units. */
        pOnfiPageParameter->onfiLogicalUnits = *(uint8_t *)(onfi_param_table + 100);
        /* Number of bits of ECC correction */
        pOnfiPageParameter->onfiEccCorrectability = *(uint8_t *)(onfi_param_table + 112);
        /* Device model */
        pOnfiPageParameter->onfiDeviceModel= *(uint8_t *)(onfi_param_table + 49);
        return 1;
    }
    return 0;
}
예제 #3
0
static PSNandInitInfo AT91F_NandReadID(void)
{
    unsigned int uChipID;

    unsigned char bManufacturerID, bDeviceID;

    /*
     * Enable chipset 
     */
    NAND_ENABLE_CE();

    /*
     * Ask the Nand its IDs 
     */
    WRITE_NAND_COMMAND(CMD_READID);
    WRITE_NAND_ADDRESS(0x00);

    /*
     * Read answer 
     */
    bManufacturerID = READ_NAND();
    bDeviceID = READ_NAND();

    /*
     * Disable chipset before returning 
     */
    NAND_DISABLE_CE();

    uChipID = (bManufacturerID << 8) | bDeviceID;

    return AT91F_GetNandInitInfo(uChipID);
}
예제 #4
0
/**
 * \brief This function check if the Nandflash has an embedded ECC controller.
 * \return  0: ONFI not compliant or internal ECC not supported.
            1: Internal ECC enabled.
*/
uint8_t NandEnableInternalEcc (void)
{
    OnfiPageParam *pOnfiPageParameter;
    pOnfiPageParameter = NandGetCurrentOnfiInstance();

    if (pOnfiPageParameter->onfiCompatiable == 1) {
        /* Check if the Nandflash has an embedded ECC controller
           Known memories with this feature :
           - Manufacturer ID = 2Ch (Micron)
           - Number of bits ECC = 04h (4-bit ECC means process 34nm)
           - device size = 1Gb or 2Gb or 4Gb (Number of data bytes per page * Number of pages per block * Number of blocks per unit)  */
        if ( ((pOnfiPageParameter->manufacturerId & NAND_MFR_MICRON) == NAND_MFR_MICRON) &&
              (pOnfiPageParameter->onfiEccCorrectability == 0x4) &&
              ((pOnfiPageParameter->onfiDeviceModel == '1')     //  1G,
               || (pOnfiPageParameter->onfiDeviceModel == '2')     //  2G
               || (pOnfiPageParameter->onfiDeviceModel == '4'))) { //  or 4G bits

            /* then activate the internal ECC controller */
            WRITE_NAND_COMMAND(NAND_CMD_SET_FEATURE, EBI_NF_ADDR);
            WRITE_NAND_ADDRESS(0x90, EBI_NF_ADDR);

            WRITE_NAND(0x08, EBI_NF_ADDR);
            WRITE_NAND(0x00, EBI_NF_ADDR);
            WRITE_NAND(0x00, EBI_NF_ADDR);
            WRITE_NAND(0x00, EBI_NF_ADDR);
            NandSwitchEcc(ECC_INTERNAL);
            return 1;
        }
    }
    return 0;
}
예제 #5
0
static void reset_nandflash(void)
{
    NAND_ENABLE_CE();
    WRITE_NAND_COMMAND(0xFF);
    NAND_WAIT_READY();
    NAND_WAIT_READY();
    NAND_DISABLE_CE();
}
예제 #6
0
/* NanD_Command: Send a flash command to the flash chip */
static int NanD_Command(unsigned char command)
{
 	NAND_CTL_SETCLE(NAND_ADDR);
 	WRITE_NAND_COMMAND(command, NAND_ADDR);
 	NAND_CTL_CLRCLE(NAND_ADDR);

  	if(command == NAND_CMD_RESET){
		unsigned char ret_val;
		NanD_Command(NAND_CMD_STATUS);
		do{
			ret_val = READ_NAND(NAND_ADDR);/* wait till ready */
  		} while((ret_val & 0x40) != 0x40);
 	}
 	
 	NAND_WAIT_READY();
	return 0;
}
예제 #7
0
파일: mtd_onfi.c 프로젝트: a1ien/nuttx
bool onfi_compatible(uintptr_t cmdaddr, uintptr_t addraddr,
                     uintptr_t dataaddr)
{
  uint8_t parmtab[ONFI_PARAM_TABLE_SIZE];

  /* Check if the Nandflash is ONFI compliant */

  WRITE_NAND_COMMAND(NAND_CMD_READID, cmdaddr);
  WRITE_NAND_ADDRESS(0x20, addraddr);

  parmtab[0] = READ_NAND(dataaddr);
  parmtab[1] = READ_NAND(dataaddr);
  parmtab[2] = READ_NAND(dataaddr);
  parmtab[3] = READ_NAND(dataaddr);

  return
   (parmtab[0] == 'O' && parmtab[1] == 'N' &&
    parmtab[2] == 'F' && parmtab[3] == 'I');
}
예제 #8
0
파일: mtd_onfi.c 프로젝트: a1ien/nuttx
bool onfi_embeddedecc(FAR const struct onfi_pgparam_s *onfi,
                      uintptr_t cmdaddr, uintptr_t addraddr,
                      uintptr_t dataaddr, bool enable)
{
  /* Does the NAND supported the embedded ECC function? */

  if (onfi_have_embeddedecc(onfi))
    {
      /* Yes... enable or disable it */
      /* Perform common setup */

      WRITE_NAND_COMMAND(NAND_CMD_SET_FEATURE, cmdaddr);
      WRITE_NAND_ADDRESS(0x90, addraddr);

      if (enable)
        {
          /* Activate the internal ECC controller */

          WRITE_NAND(0x08, dataaddr);
          WRITE_NAND(0x00, dataaddr);
          WRITE_NAND(0x00, dataaddr);
          WRITE_NAND(0x00, dataaddr);
          setSmcOpEccType(SMC_ECC_INTERNAL);
        }
      else
        {
          /* De-activate the internal ECC controller */

          WRITE_NAND(0x00, dataaddr);
          WRITE_NAND(0x00, dataaddr);
          WRITE_NAND(0x00, dataaddr);
          WRITE_NAND(0x00, dataaddr);
        }

      return true;
    }

  return false;
}
예제 #9
0
파일: mtd_onfi.c 프로젝트: a1ien/nuttx
static int onfi_readstatus(uintptr_t cmdaddr, uintptr_t dataaddr)
{
  uint32_t timeout;
  uint8_t status;

  /* Issue command */

  WRITE_NAND_COMMAND(NAND_CMD_STATUS, cmdaddr);
  timeout = 0;

  while (timeout < MAX_READ_STATUS_COUNT)
    {
      /* Read status byte */

      status = READ_NAND(dataaddr);

      /* Check status. If status bit 6 = 1 device is ready */

      if ((status & STATUS_BIT_6) == STATUS_BIT_6)
        {
          /* If status bit 0 = 0 the last operation was successful */

          if ((status & STATUS_BIT_0) == 0)
            {
              return OK;
            }
          else
            {
              return -EIO;
            }
        }

      timeout++;
    }

  return -ETIMEDOUT;
}
예제 #10
0
/**
 * \brief This function Reads the status register of the NAND device by 
 * issuing a 0x70 command.
 * \return  NAND_IO_RC_PASS     =0 : The function completes operation successfully.
            NAND_IO_RC_FAIL     =1 : The function does not complete operation successfully.
            NAND_IO_RC_TIMEOUT  =2 : The function times out before operation completes.
*/
static uint32_t _NandReadStatus(void)
{
    uint32_t nReadStatusCount;
    uint8_t ucStatus;

    /* Issue command */
    WRITE_NAND_COMMAND(NAND_CMD_STATUS, EBI_NF_ADDR);
    nReadStatusCount = 0;

    while (nReadStatusCount < MAX_READ_STATUS_COUNT) {
        /* Read status byte */
        ucStatus = READ_NAND(EBI_NF_ADDR);
        /* Check status */
        /* If status bit 6 = 1 device is ready */
        if ((ucStatus & STATUS_BIT_6) == STATUS_BIT_6) {
            if ((ucStatus & STATUS_BIT_0) == 0)  /* If status bit 0 = 0 the last operation was succesful */
                return NAND_IO_RC_PASS;
            else
                return NAND_IO_RC_FAIL;
        }
        nReadStatusCount++;
    }
    return NAND_IO_RC_TIMEOUT;
}
예제 #11
0
/**
 * \brief This function read an the ONFI signature at address of 20h to detect
 * if the device is ONFI compatiable.
 * \return  0: ONFI not compliant or not supported.
            1: ONFI compliant
*/
uint8_t NandIsOnficompatible (void)
{
    uint8_t onfi_param_table[ONFI_PARAM_TABLE_SIZE];

    // Check if the Nandflash is ONFI compliant

    WRITE_NAND_COMMAND(NAND_CMD_READID, EBI_NF_ADDR);
    WRITE_NAND_ADDRESS(0x20, EBI_NF_ADDR);

    onfi_param_table[0] = READ_NAND(EBI_NF_ADDR);
    onfi_param_table[1] = READ_NAND(EBI_NF_ADDR);
    onfi_param_table[2] = READ_NAND(EBI_NF_ADDR);
    onfi_param_table[3] = READ_NAND(EBI_NF_ADDR);

    if ((onfi_param_table[0] == 'O') &&
        (onfi_param_table[1] == 'N') &&
        (onfi_param_table[2] == 'F') &&
        (onfi_param_table[3] == 'I')) {
        return 1;
    }
    else {
        return 0;
    }
}
예제 #12
0
uint8_t NandEbiDetect(void)
{
    uint32_t timer;
    uint8_t rc;
    uint8_t chip_found = 0;
    uint8_t ids[4];
    uint8_t i;
    
    *ADDR_CCFG_EBICSA |= EBICSA_EBI_DBPDC;
    /* Try to detect a bootable Nand connected on D16 */
    *ADDR_CCFG_EBICSA |= (EBICSA_NAND_D0_ON_D16 );
 
    /* Send Reset command */
    WRITE_NAND_COMMAND(NAND_CMD_RESET, EBI_NF_ADDR);
    /* If a Nandflash is connected, it should answer to a read status command */
    for (timer = 0; timer < 60; timer++) {
        rc = _NandReadStatus();
        if (rc == NAND_IO_RC_PASS) {
            WRITE_NAND_COMMAND(NAND_CMD_READID, EBI_NF_ADDR);
            WRITE_NAND_ADDRESS(0, EBI_NF_ADDR);
            ids[0] = READ_NAND(EBI_NF_ADDR);
            ids[1] = READ_NAND(EBI_NF_ADDR);
            ids[2] = READ_NAND(EBI_NF_ADDR);
            ids[3] = READ_NAND(EBI_NF_ADDR);
            for(i = 0; i< NandFlashModelList_SIZE ; i++) {
                if(nandFlashModelList[i].deviceId == ids[1]) {
                    chip_found = 1;
                    break;
                }
            }
            break;
        }
    }
    if (chip_found == 0) {

        /* Then try Nand connected on D0 */
        *ADDR_CCFG_EBICSA &= (uint32_t)(~ EBICSA_NAND_D0_ON_D16 );

        /* Send Reset command */
        WRITE_NAND_COMMAND(NAND_CMD_RESET, EBI_NF_ADDR);

        /* If a Nandflash is connected, it should answer to a read status command */
        for (timer = 0; timer < 60; timer++) {
            rc = _NandReadStatus();
            if (rc == NAND_IO_RC_PASS) {
                WRITE_NAND_COMMAND(NAND_CMD_READID, EBI_NF_ADDR);
                WRITE_NAND_ADDRESS(0, EBI_NF_ADDR);
                ids[0] = READ_NAND(EBI_NF_ADDR);
                ids[1] = READ_NAND(EBI_NF_ADDR);
                ids[2] = READ_NAND(EBI_NF_ADDR);
                ids[3] = READ_NAND(EBI_NF_ADDR);
                for( i = 0; i< NandFlashModelList_SIZE ; i++) {
                    if(nandFlashModelList[i].deviceId == ids[1]) {
                        chip_found = 1;
                        break;
                    }
                }
            }
            break;
        }
    }
    return chip_found;
}
예제 #13
0
파일: mtd_onfi.c 프로젝트: a1ien/nuttx
int onfi_read(uintptr_t cmdaddr, uintptr_t addraddr, uintptr_t dataaddr,
              FAR struct onfi_pgparam_s *onfi)
{
  uint8_t parmtab[ONFI_PARAM_TABLE_SIZE];
  int i;

  finfo("cmdaddr=%08x addraddr=%08x dataaddr=%08x\n",
        (int)cmdaddr, (int)addraddr, (int)dataaddr);

  if (!onfi_compatible(cmdaddr, addraddr, dataaddr))
    {
      ferr("ERROR: No ONFI compatible device detected\n");
      return -ENODEV;
    }

  /* Initialize the ONFI parameter table */

  memset(parmtab, 0xff, ONFI_PARAM_TABLE_SIZE);

  /* Perform Read Parameter Page command */

  WRITE_NAND_COMMAND(NAND_CMD_READ_PARAM_PAGE, cmdaddr);
  WRITE_NAND_ADDRESS(0x0, addraddr);

  /* Wait NF ready */

  onfi_readstatus(cmdaddr, dataaddr);

  /* Re-enable data output mode required after Read Status command */

  WRITE_NAND_COMMAND(NAND_CMD_READ0, cmdaddr);

  /* Read the parameter table */

  for (i = 0; i < ONFI_PARAM_TABLE_SIZE; i++)
    {
      parmtab[i] = READ_NAND(dataaddr);
    }

  for (i = 0; i < ONFI_PARAM_TABLE_SIZE; i++)
    {
      if (parmtab[i] != 0xff)
        {
          break;
        }
    }

  if (i == ONFI_PARAM_TABLE_SIZE)
    {
      ferr("ERROR: Failed to read ONFI parameter table\n");
      return -EIO;
   }

  /* JEDEC manufacturer ID */

  onfi->manufacturer = *(FAR uint8_t *)(parmtab + 64);

  /* Bus width */

  onfi->buswidth = (*(FAR uint8_t *)(parmtab + 6)) & 0x01;

  /* Get number of data bytes per page (bytes 80-83 in the param table) */

  onfi->pagesize =  *(FAR uint32_t *)(FAR void *)(parmtab + 80);

  /* Get number of spare bytes per page (bytes 84-85 in the param table) */

  onfi->sparesize =  *(FAR uint16_t *)(FAR void *)(parmtab + 84);

  /* Number of pages per block. */

  onfi->pagesperblock = *(FAR uint32_t *)(FAR void *)(parmtab + 92);

  /* Number of blocks per logical unit (LUN). */

  onfi->blocksperlun = *(FAR uint32_t *)(FAR void *)(parmtab + 96);

  /* Number of logical units. */

  onfi->luns = *(FAR uint8_t *)(parmtab + 100);

  /* Number of bits of ECC correction */

  onfi->eccsize = *(FAR uint8_t *)(parmtab + 112);

  /* Device model */

  onfi->model = *(FAR uint8_t *)(parmtab + 49);

  finfo("Returning:\n");
  finfo("  manufacturer:  0x%02x\n", onfi->manufacturer);
  finfo("  buswidth:      %d\n",     onfi->buswidth);
  finfo("  luns:          %d\n",     onfi->luns);
  finfo("  eccsize:       %d\n",     onfi->eccsize);
  finfo("  model:         0x%02s\n", onfi->model);
  finfo("  sparesize:     %d\n",     onfi->sparesize);
  finfo("  pagesperblock: %d\n",     onfi->pagesperblock);
  finfo("  blocksperlun:  %d\n",     onfi->blocksperlun);
  finfo("  pagesize:      %d\n",     onfi->pagesize);
  return OK;
}