Esempio n. 1
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;
}
Esempio n. 2
0
//-----------------------------------------------------------------------------
__inline
void
SectorAccess(
    NandDevice_t* pDevice, 
    SECTOR_ADDR sector,
    UINT offset
    )
{
    
    // Offset is provided to this function in bytes; NAND device requires words
    offset = offset / 2;
    WRITE_NAND(pDevice->pNandAddress, (offset & 0xFF));
    WRITE_NAND(pDevice->pNandAddress, ((offset >> 8) & 0xFF));
    WRITE_NAND(pDevice->pNandAddress, (sector & 0xFF));
    WRITE_NAND(pDevice->pNandAddress, ((sector >> 8) & 0xFF));
    WRITE_NAND(pDevice->pNandAddress, ((sector >> 16) & 0xFF));
}
/*!
  \fn void ifx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
  \ingroup  IFX_NAND_DRV
  \brief  write buffer to chip
  \param  mtd   MTD device structure
  \param  buf   data buffer
  \param  len   number of bytes to write
  \return none
*/   
static void ifx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
{
        int i;
        //struct nand_chip *chip = mtd->priv;

        for (i = 0; i < len; i++)
               WRITE_NAND(buf[i]);
             // writeb(buf[i], chip->IO_ADDR_W);
}
Esempio n. 4
0
//-----------------------------------------------------------------------------
__inline
void
BlockAccess(
    NandDevice_t* pDevice,
    BLOCK_ID blockId
    )
{
    blockId *= pDevice->nandInfo.sectorsPerBlock;
    WRITE_NAND(pDevice->pNandAddress, (blockId & 0xFF));
    WRITE_NAND(pDevice->pNandAddress, ((blockId >> 8) & 0xFF));
    WRITE_NAND(pDevice->pNandAddress, ((blockId >> 16) & 0xFF));
}
Esempio n. 5
0
static void upmnand_write_byte(struct mtd_info *mtdinfo, u_char byte)
{
	struct nand_chip *this = mtdinfo->priv;
	ulong base = (ulong) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);

	if (hwctl & 0x1) {
		WRITE_NAND_UPM(byte, base, CONFIG_SYS_NAND_UPM_WRITE_CMD_OFS);
	} else if (hwctl & 0x2) {
		WRITE_NAND_UPM(byte, base, CONFIG_SYS_NAND_UPM_WRITE_ADDR_OFS);
	} else {
		WRITE_NAND(byte, base);
	}
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
//-----------------------------------------------------------------------------
HANDLE 
NAND_Initialize(
    LPCTSTR szContext,
    PCI_REG_INFO *pRegIn,
    PCI_REG_INFO *pRegOut
    )
{
    DWORD chipSelect = BSPGetNandCS();
    const NAND_INFO *  pBSPNandInfo;
    HANDLE hDevice = NULL;
    UINT ffPrefetchMode = 0;
    UINT8 manufacturer, device;
    NandDevice_t *pDevice = &s_Device;
#ifndef BOOT_MODE    
    DWORD dwKernelRet;
#endif

    UNREFERENCED_PARAMETER(pRegOut);
    UNREFERENCED_PARAMETER(szContext);
    // initialize structure
    memset(pDevice, 0, sizeof(NandDevice_t));

#ifdef BOOT_MODE    
    pDevice->pGpmcRegs = (OMAP_GPMC_REGS*)OALPAtoUA(SOCGetGPMCAddress(0));
    pDevice->pFifo = (NANDREG*)OALPAtoUA(pRegIn->MemBase.Reg[0]);

    /* Get ECC mode from BootCfg */
    pDevice->ECCtype = g_ecctype;
    if((pDevice->ECCtype > BCH8bit) || (pDevice->ECCtype < Hamming1bit))
    	{
            pDevice->ECCtype = Hamming1bit;
            RETAILMSG(TRUE, (L"Incorrect ECC type setting\r\n"));			
    	}
#else    
    if (szContext != NULL)
	{
        if (InitializePointers(szContext, pDevice) == FALSE) goto cleanUp;
	}
    else
	{
        PHYSICAL_ADDRESS pa;
        
        // if there's not context string then use global macros

        pa.QuadPart = pRegIn->MemBase.Reg[0];
        pDevice->memLen[0] = pRegIn->MemLen.Reg[0];
        pDevice->pGpmcRegs = MmMapIoSpace(pa, pDevice->memLen[0], FALSE);
        if (pDevice->pGpmcRegs == NULL) goto cleanUp;

        pa.QuadPart = pRegIn->MemBase.Reg[1];
        pDevice->memLen[1] = pRegIn->MemLen.Reg[1];
        pDevice->pFifo = MmMapIoSpace(pa, pDevice->memLen[1], FALSE);
        if (pDevice->pGpmcRegs == NULL) goto cleanUp;

	}

	if (!KernelIoControl(IOCTL_HAL_GET_ECC_TYPE, NULL, 0, &pDevice->ECCtype, sizeof(DWORD), &dwKernelRet))
	{
		RETAILMSG( TRUE,(TEXT("Failed to read Ecc type\r\n")));
		pDevice->ECCtype = Hamming1bit;
	}   
	
	RETAILMSG(TRUE, (L"ECC TYPE is %s\r\n", (pDevice->ECCtype==Hamming1bit)? L"Hamming 1 bit" :
									(pDevice->ECCtype==BCH4bit)? L"BCH 4 bit" : L"BCH 8 bit"));
	
#endif

    pDevice->pNandCmd = (NANDREG*)((UINT32)pDevice->pGpmcRegs + offset(OMAP_GPMC_REGS, GPMC_NAND_COMMAND_0) + (0x30 * chipSelect));
    pDevice->pNandAddress= (NANDREG*)((UINT32)pDevice->pGpmcRegs + offset(OMAP_GPMC_REGS, GPMC_NAND_ADDRESS_0) + (0x30 * chipSelect));
    pDevice->pNandData= (NANDREG*)((UINT32)pDevice->pGpmcRegs + offset(OMAP_GPMC_REGS, GPMC_NAND_DATA_0) + (0x30 * chipSelect));
    // Enable GPMC wait-to-nowait edge detection mechanism on NAND R/B pin
    NAND_Enable(pDevice, TRUE);

    // Write RESET command
    // (a reset aborts any current READ, WRITE (PROGRAM) or ERASE operation)
    NAND_SendCommand(pDevice, NAND_CMD_RESET);

    // Wait for NAND
    while ((NAND_GetStatus(pDevice) & NAND_STATUS_READY) == 0);

    // Send Read ID Command
    NAND_SendCommand(pDevice, NAND_CMD_READID);

    // Send Address 00h
    WRITE_NAND(pDevice->pNandAddress, 0);

    // Read the manufacturer ID & device code
    manufacturer = (UINT8)READ_NAND(pDevice->pNandData);
    device = (UINT8)READ_NAND(pDevice->pNandData);

 
    if ((pBSPNandInfo = BSPGetNandInfo(manufacturer,device))==NULL)
    {                
        goto cleanUp;
    }
    if ((pBSPNandInfo->sectorSize != 2048) && (pBSPNandInfo->wordData != 2))
    {
        ERRORMSG(1,(TEXT("FMD driver supports only 16bits large page (2KB) devices\r\n")));
        goto cleanUp;
    }
    pDevice->nandInfo = *pBSPNandInfo;

    pDevice->IrqWait = BSPGetNandIrqWait();

    /* ECCCfg: 16bit bus width, cs0, 4 - 512 bytes blocks per page */
    pDevice->ECCCfg = (GPMC_ECC_CONFIG_16BIT | (chipSelect << 1) | (0x3<<4)); 
    pDevice->ECCsize = (pDevice->ECCtype == Hamming1bit ) ? ECC_BYTES_HAMMING : 
		                      (pDevice->ECCtype == BCH4bit ) ? ECC_BYTES_BCH4 : ECC_BYTES_BCH8; 
							  
    //  Enable and reset ECC engine (workaround for engine giving 0s first time)
    ECC_Init(pDevice->pGpmcRegs, pDevice->ECCCfg, pDevice->ECCtype, NAND_ECC_READ);
    ECC_Reset(pDevice->pGpmcRegs);

    //  Only enable during NAND read/write/erase operations
    NAND_Enable(pDevice, FALSE);

    // configure the prefetch engine
    pDevice->prefetchMode = kPrefetchOff;
    OUTREG32(&pDevice->pGpmcRegs->GPMC_PREFETCH_CONTROL, 0);

    // set prefetch mask
    ffPrefetchMode = GPMC_PREFETCH_CONFIG_SYNCHROMODE |
                     GPMC_PREFETCH_CONFIG_PFPWENROUNDROBIN |
                     GPMC_PREFETCH_CONFIG_ENABLEOPTIMIZEDACCESS |
                     GPMC_PREFETCH_CONFIG_WAITPINSELECTOR(chipSelect) |
                     GPMC_PREFETCH_CONFIG_FIFOTHRESHOLD(FIFO_THRESHOLD) |
                     GPMC_PREFETCH_CONFIG_ENGINECSSELECTOR(chipSelect);

    OUTREG32(&pDevice->pGpmcRegs->GPMC_PREFETCH_CONFIG1, ffPrefetchMode);

    // configure prefetch engine
    OUTREG32(&pDevice->pGpmcRegs->GPMC_PREFETCH_CONFIG2, 
        pBSPNandInfo->sectorSize
        );
        
    SETREG32(&pDevice->pGpmcRegs->GPMC_PREFETCH_CONFIG1, 
        GPMC_PREFETCH_CONFIG_ENABLEENGINE
        );

    // We are done
    hDevice = pDevice;

cleanUp:
    return hDevice;
}