From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- memories/norflash/NorFlashIntel.c | 416 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 memories/norflash/NorFlashIntel.c (limited to 'memories/norflash/NorFlashIntel.c') diff --git a/memories/norflash/NorFlashIntel.c b/memories/norflash/NorFlashIntel.c new file mode 100644 index 0000000..15c1ea3 --- /dev/null +++ b/memories/norflash/NorFlashIntel.c @@ -0,0 +1,416 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ +#include "NorFlashCFI.h" +#include "NorFlashCommon.h" +#include +#include + +//------------------------------------------------------------------------------ +// Local defination +//------------------------------------------------------------------------------ + +/// Command for vendor command set CMD_SET_INTEL. Device commands are written +/// to the Command User Interface (CUI) to control all flash memory device operations. +#define INTEL_CMD_IDIN 0x0090 +#define INTEL_CMD_BLOCK_ERASE_1 0x0020 +#define INTEL_CMD_BLOCK_ERASE_2 0x00D0 +#define INTEL_CMD_READ_STATUS 0x0070 +#define INTEL_CMD_CLEAR_STATUS 0x0050 +#define INTEL_CMD_BLOCK_LOCKSTART 0x0060 +#define INTEL_CMD_BLOCK_LOCK 0x0001 +#define INTEL_CMD_BLOCK_UNLOCK 0x00D0 +#define INTEL_CMD_BLOCK_LOCKDOWN 0x002F +#define INTEL_CMD_PROGRAM_WORD 0x0010 +#define INTEL_CMD_RESET 0x00FF + + +/// Intel norflash status resgister +#define INTEL_STATUS_DWS 0x80 +#define INTEL_STATUS_ESS 0x40 +#define INTEL_STATUS_ES 0x20 +#define INTEL_STATUS_PS 0x10 +#define INTEL_STATUS_VPPS 0x08 +#define INTEL_STATUS_PSS 0x04 +#define INTEL_STATUS_BLS 0x02 +#define INTEL_STATUS_BWS 0x01 + +/// Intel norflash device Identifier infomation address offset. +#define INTEL_MANU_ID 0x00 +#define INTEL_DEVIDE_ID 0x01 +#define INTEL_LOCKSTATUS 0x02 + +/// Intel norflash device lock status. +#define INTEL_LOCKSTATUS_LOCKED 0x01 +#define INTEL_LOCKSTATUS_LOCKDOWNED 0x02 + +//------------------------------------------------------------------------------ +// Local functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// It implements a RESET command. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +//------------------------------------------------------------------------------ +void intel_Reset(struct NorFlashInfo *pNorFlashInfo, unsigned int address) +{ + unsigned int busAddress; + unsigned int busWidth; + busWidth = NorFlash_GetDataBusWidth(pNorFlashInfo); + busAddress = NorFlash_GetAddressInChip(pNorFlashInfo, address); + WriteCommand(busWidth, busAddress, INTEL_CMD_RESET); +} + + +//------------------------------------------------------------------------------ +/// The Read Device Identifier command instructs the device to output manufacturer +/// code, device identifier code, block-lock status, protection register data, +/// or configuration register data by giving offset. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +/// \param offset 0: Identifier address offset. +//------------------------------------------------------------------------------ +unsigned int intel_ReadIdentification( + struct NorFlashInfo *pNorFlashInfo, + unsigned int offset) +{ + unsigned int data; + unsigned char busWidth; + unsigned int address; + + // Issue Read Array Command - just in case that the flash is not in Read Array mode + intel_Reset(pNorFlashInfo, 0); + busWidth = NorFlash_GetDataBusWidth(pNorFlashInfo); + address = NorFlash_GetAddressInChip(pNorFlashInfo, offset); + // Issue the Read Device Identifier command at specified address. + WriteCommand(busWidth, address, INTEL_CMD_IDIN); + ReadRawData(busWidth, address, (unsigned char*)&data); + + intel_Reset(pNorFlashInfo, 0); + return data; +} + + +//------------------------------------------------------------------------------ +/// Return the status register value. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +//------------------------------------------------------------------------------ +unsigned char intel_ReadStatus(struct NorFlashInfo *pNorFlashInfo, unsigned int address) +{ + unsigned int status; + unsigned char busWidth; + unsigned int budAddress; + busWidth = NorFlash_GetDataBusWidth(pNorFlashInfo); + + // Issue the Read Status Register command at any address. + budAddress = NorFlash_GetAddressInChip(pNorFlashInfo, address), + WriteCommand(busWidth, budAddress, INTEL_CMD_READ_STATUS); + ReadRawData(busWidth, budAddress, (unsigned char*)&status); + return status; +} + +//------------------------------------------------------------------------------ +/// Clear the status register. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +//------------------------------------------------------------------------------ +void intel_ClearStatus(struct NorFlashInfo *pNorFlashInfo) +{ + unsigned char busWidth; + unsigned int address; + busWidth = NorFlash_GetDataBusWidth(pNorFlashInfo); + + // Issue the Clear Status Register command at any address + address = NorFlash_GetAddressInChip(pNorFlashInfo, 0), + WriteCommand(busWidth, address, INTEL_CMD_CLEAR_STATUS); +} + +//------------------------------------------------------------------------------ +/// Unlocks the specified block of the device. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +/// \param address Address in sector. +//------------------------------------------------------------------------------ +void intel_UnlockSector(struct NorFlashInfo *pNorFlashInfo, unsigned int address) +{ + unsigned int busAddress; + unsigned char busWidth; + // Issue Read Array Command - just in case that the flash is not in Read Array mode + intel_Reset(pNorFlashInfo, 0); + // Clear the status register first. + + busWidth = NorFlash_GetDataBusWidth(pNorFlashInfo); + busAddress = NorFlash_GetAddressInChip(pNorFlashInfo,address); + + WriteCommand(busWidth, busAddress, INTEL_CMD_BLOCK_LOCKSTART); + WriteCommand(busWidth, busAddress, INTEL_CMD_BLOCK_UNLOCK); + intel_Reset(pNorFlashInfo, 0); +} + +//------------------------------------------------------------------------------ +/// The Read Device Identifier command instructs the device to output block-lock +/// status. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +/// \param address 0: Address in sector/block. +//------------------------------------------------------------------------------ +unsigned int intel_GetBlockLockStatus(struct NorFlashInfo *pNorFlashInfo, unsigned int address) +{ + return intel_ReadIdentification(pNorFlashInfo, (address + NorFlash_GetByteAddress(pNorFlashInfo ,INTEL_LOCKSTATUS))); +} + +//------------------------------------------------------------------------------ +/// It implement a program word command. Returns 0 if the operation was +/// successful; otherwise returns an error code. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +/// \param address Start address offset to be wrote. +/// \param data word to be written. +//------------------------------------------------------------------------------ +unsigned char intel_Program( + struct NorFlashInfo *pNorFlashInfo, + unsigned int address, + unsigned int data + ) +{ + unsigned int status; + unsigned int datain; + volatile unsigned int busAddress; + unsigned char done = 0; + unsigned char busWidth; + + busWidth = NorFlash_GetDataBusWidth(pNorFlashInfo); + // Issue Read Array Command - just in case that the flash is not in Read Array mode + intel_Reset(pNorFlashInfo, address); + + busAddress = NorFlash_GetAddressInChip(pNorFlashInfo, address); + /* + // Check if the data already have been erased. + ReadRawData(busWidth, busAddress, (unsigned char*)&datain); + if((datain & data)!= data) { + return NorCommon_ERROR_CANNOTWRITE; + } + */ + // Word programming operations are initiated by writing the Word Program Setup command to the device. + WriteCommand(busWidth, busAddress, INTEL_CMD_PROGRAM_WORD); + // This is followed by a second write to the device with the address and data to be programmed. + WriteRawData(busWidth, busAddress, (unsigned char*)&data); + + // Status register polling + do { + status = intel_ReadStatus(pNorFlashInfo,address); + // Check if the device is ready. + if ((status & INTEL_STATUS_DWS) == INTEL_STATUS_DWS ) { + // check if VPP within acceptable limits during program or erase operation. + if ((status & INTEL_STATUS_VPPS) == INTEL_STATUS_VPPS ) { + return NorCommon_ERROR_CANNOTWRITE; + } + // Check if the erase block operation is completed. + if ((status & INTEL_STATUS_PS) == INTEL_STATUS_PS ) { + return NorCommon_ERROR_CANNOTWRITE; + } + // check if Block locked during program or erase, operation aborted. + else if ((status & INTEL_STATUS_BLS) == INTEL_STATUS_BLS ) { + return NorCommon_ERROR_CANNOTWRITE; + } + else { + done = 1; + } + } + } while (!done); + + intel_ClearStatus(pNorFlashInfo); + intel_Reset(pNorFlashInfo, address); + return 0; +} + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// It implements a RESET command. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +//------------------------------------------------------------------------------ +void INTEL_Reset(struct NorFlashInfo *pNorFlashInfo, unsigned int address) +{ + intel_Reset(pNorFlashInfo, address); +} + +//------------------------------------------------------------------------------ +/// The Read Device Identifier command instructs the device to output manufacturer +/// code. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +//------------------------------------------------------------------------------ +unsigned int INTEL_ReadManufactoryId(struct NorFlashInfo *pNorFlashInfo) +{ + return intel_ReadIdentification(pNorFlashInfo, INTEL_MANU_ID); +} + +//------------------------------------------------------------------------------ +/// The Read Device Identifier command instructs the device to output device id. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +//------------------------------------------------------------------------------ +unsigned int INTEL_ReadDeviceID(struct NorFlashInfo *pNorFlashInfo) +{ + return intel_ReadIdentification(pNorFlashInfo, INTEL_DEVIDE_ID); +} + +//------------------------------------------------------------------------------ +/// Erases the specified block of the device. Returns 0 if the operation was +/// successful; otherwise returns an error code. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +/// \param address Address offset to be erase. +//------------------------------------------------------------------------------ +unsigned char INTEL_EraseSector( + struct NorFlashInfo *pNorFlashInfo, + unsigned int address) +{ + unsigned int status; + unsigned int busAddress; + unsigned char busWidth; + unsigned char done = 0; + + busWidth = NorFlash_GetDataBusWidth(pNorFlashInfo); + // Issue Read Array Command - just in case that the flash is not in Read Array mode + intel_Reset(pNorFlashInfo, address); + + // Check the lock status is locked. + status = intel_GetBlockLockStatus(pNorFlashInfo, address); + if(( status & INTEL_LOCKSTATUS_LOCKED ) == INTEL_LOCKSTATUS_LOCKED){ + intel_UnlockSector(pNorFlashInfo, address); + } + // Clear the status register first. + intel_ClearStatus(pNorFlashInfo); + busAddress = NorFlash_GetAddressInChip(pNorFlashInfo,address); + // Block erase operations are initiated by writing the Block Erase Setup command to the address of the block to be erased. + WriteCommand(busWidth, busAddress, INTEL_CMD_BLOCK_ERASE_1); + // Next, the Block Erase Confirm command is written to the address of the block to be erased. + WriteCommand(busWidth, busAddress, INTEL_CMD_BLOCK_ERASE_2); + // Status register polling + do { + status = intel_ReadStatus(pNorFlashInfo,address); + // Check if the device is ready. + if ((status & INTEL_STATUS_DWS) == INTEL_STATUS_DWS ) { + // check if VPP within acceptable limits during program or erase operation. + if ((status & INTEL_STATUS_VPPS) == INTEL_STATUS_VPPS ) { + intel_Reset(pNorFlashInfo, 0); + return NorCommon_ERROR_CANNOTWRITE; + } + // Check if the erase block operation is completed. + if ((status & INTEL_STATUS_PS) == INTEL_STATUS_PS ) { + intel_Reset(pNorFlashInfo, 0); + return NorCommon_ERROR_CANNOTWRITE; + } + // Check if the erase block operation is completed. + if ((status & INTEL_STATUS_ES) == INTEL_STATUS_ES ) { + intel_Reset(pNorFlashInfo, 0); + return NorCommon_ERROR_CANNOTWRITE; + } + + // check if Block locked during program or erase, operation aborted. + else if ((status & INTEL_STATUS_BLS) == INTEL_STATUS_BLS ) { + intel_Reset(pNorFlashInfo, 0); + return NorCommon_ERROR_CANNOTWRITE; + } + else { + done = 1; + } + } + } while (!done); + intel_Reset(pNorFlashInfo, address); + return 0; +} + +//------------------------------------------------------------------------------ +/// Erases all the block of the device. Returns 0 if the operation was successful; +/// otherwise returns an error code. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +//------------------------------------------------------------------------------ + +unsigned char INTEL_EraseChip(struct NorFlashInfo *pNorFlashInfo) +{ + // Interl flash have no independent Chip-erase command. + unsigned int i; + unsigned int sectors; + sectors = NorFlash_GetDeviceNumOfBlocks(pNorFlashInfo); + for (i = 0; i < sectors; i++) { + if (INTEL_EraseSector(pNorFlashInfo, NorFlash_GetDeviceSectorAddress(pNorFlashInfo, i))) { + return NorCommon_ERROR_CANNOTERASE; + } + } + return 0; +} + +//------------------------------------------------------------------------------ +/// Sends data to the struct NorFlashInfo chip from the provided buffer. +/// \param pNorFlashInfo Pointer to an struct NorFlashInfo instance. +/// \param address Start address offset to be wrote. +/// \param buffer Buffer where the data is stored. +/// \param size Number of bytes that will be written. +//------------------------------------------------------------------------------ +unsigned char INTEL_Write_Data( + struct NorFlashInfo *pNorFlashInfo, + unsigned int address, + unsigned char *buffer, + unsigned int size) +{ + unsigned int i; + unsigned char busWidth; + + busWidth = pNorFlashInfo->deviceChipWidth; + if (busWidth == FLASH_CHIP_WIDTH_8BITS ){ + for(i=0; i < size; i++) { + if(intel_Program(pNorFlashInfo, address, buffer[i])) { + return NorCommon_ERROR_CANNOTWRITE; + } + address ++; + } + } + else if( busWidth == FLASH_CHIP_WIDTH_16BITS ){ + unsigned short *buffer16 = (unsigned short *) buffer; + size = (size + 1) >> 1; + for(i=0; i < size; i++) { + + if(intel_Program(pNorFlashInfo, address, buffer16[i])){ + return NorCommon_ERROR_CANNOTWRITE; + } + address+= 2; + } + } + else if(busWidth == FLASH_CHIP_WIDTH_32BITS ){ + unsigned int *buffer32 = (unsigned int *) buffer; + size = (size + 3) >> 2; + for(i=0; i < size; i++) { + if(intel_Program(pNorFlashInfo, address, buffer32[i])){ + return NorCommon_ERROR_CANNOTWRITE; + } + address+= 4; + } + } + return 0; +} -- cgit v1.2.3