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

📄 flash_intel.c

📁 Embeded bootloader (rrload by ridgerun) for TI linux based platform v5.36
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * File: flash_intel.c * * An implementation of a flash utility specific to several Intel chipsets. * This implementation, while vendor *dependent*, exposes the vendor * *independent* flash.h interface allowing it to plug generically into the * bootloader. Please see flash.h for more info. * * See Also *    flash.h * * Copyright (C) 2002 RidgeRun, Inc. * Author: RidgeRun, Inc  <skranz@ridgerun.com> * *  This program is free software; you can redistribute  it and/or modify it *  under  the terms of  the GNU General  Public License as published by the *  Free Software Foundation;  either version 2 of the  License, or (at your *  option) any later version. * *  THIS  SOFTWARE  IS  PROVIDED  ``AS  IS''  AND   ANY  EXPRESS  OR IMPLIED *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN *  NO  EVENT  SHALL   THE AUTHOR  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. * *  You should have received a copy of the  GNU General Public License along *  with this program; if not, write  to the Free Software Foundation, Inc., *  675 Mass Ave, Cambridge, MA 02139, USA. * * Please report all bugs/problems to the author or <support@dsplinux.net> * * key: RRGPLCR (do not remove) * */#include "flash.h"#include "types.h"#include "util.h"#include "io.h"#include "memconfig.h"extern unsigned long FlashLockMode; // This is a global variable that will                                    // be tested by the flash*.c module before                                    // erases or writes flash. If the special                                    // code 0xBEEFFEED is not present here then                                    // the all flash mod operations will fail                                    // and report a flash locked state.static short TotalSectors;typedef struct {  int start_addr;  int end_addr;} sect_info_t;#if (BSPCONF_FLASH_TYPE == INTEL_28F128)#define NUM_SEQUENTIAL_CHIPS 1#endif#if (BSPCONF_FLASH_TYPE == INTEL_28F160)#define NUM_SEQUENTIAL_CHIPS 1#endif#if (BSPCONF_FLASH_TYPE == INTEL_28F320)#define NUM_SEQUENTIAL_CHIPS 1#endif#if (BSPCONF_FLASH_TYPE == INTEL_28F320x2)#define NUM_SEQUENTIAL_CHIPS 2#endif#ifdef C5471#define TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS /* e.g. interleaved */#endif#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS  #define XYZ 2#else  #define XYZ 1#endif#define NUM_CHIP_SECT 39static const int sect_sizes[NUM_CHIP_SECT] = {  // Intel 28F160F3 (2 MBytes each)  /* Avoid confusion;     Values here represented in "bytes(8bits)-per-block"; data sheet shows "words(16bits)-per-block".     the XYZ used below is usually a value of 1 except in cases where the h/w designers have     combined two flash chips side-by-side (interleaved) instead of sequentially in the     address space. In the interleaved mode a 32bit value is retrieved by the h/w     by accessing 16bits from one chip and the other 16bits from the second chip.     On the other hand, in a sequential flash design, a 32bit value is retrieved     by the h/w by accessing 16bits from a flash chip and then incrementing to the     next location within that same flash chip to get the second 16bits. In both     cases it is all seamless to the s/w since the h/w SDRAM controller is performing     all the necessary accesses to reference the 32bit value. The one area that is     not seamless to the s/w, however, is the erase-block size. In interleaved designs     the s/w needs to be aware that the minimum number of bytes that can be erased     at any one time is *twice* the minimum for each individual chip. Hence the XYZ     modifier below to help manage that.  */  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000};#define NUM_CHIP_SECT_A 71static const int sect_sizes_A[NUM_CHIP_SECT_A] = {  // Intel 28F320-Top-Boot (4MBytes each)  /* Avoid confusion;     Values here represented in "bytes(8bits)-per-block"; data sheet shows "words(16bits)-per-block".     the XYZ used below is usually a value of 1 except in cases where the h/w designers have     combined two flash chips side-by-side (interleaved) instead of sequentially in the     address space. In the interleaved mode a 32bit value is retrieved by the h/w     by accessing 16bits from one chip and the other 16bits from the second chip.     On the other hand, in a sequential flash design, a 32bit value is retrieved     by the h/w by accessing 16bits from a flash chip and then incrementing to the     next location within that same flash chip to get the second 16bits. In both     cases it is all seamless to the s/w since the h/w SDRAM controller is performing     all the necessary accesses to reference the 32bit value. The one area that is     not seamless to the s/w, however, is the erase-block size. In interleaved designs     the s/w needs to be aware that the minimum number of bytes that can be erased     at any one time is *twice* the minimum for each individual chip. Hence the XYZ     modifier below to help manage that.  */  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000, XYZ*0x10000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,  XYZ*0x2000,};#define NUM_CHIP_SECT_B 128static const int sect_sizes_B[NUM_CHIP_SECT_B] = {  // Intel 28F128J3A (16MBytes each)  /* Avoid confusion;     Values here represented in "bytes(8bits)-per-block"; data sheet shows "words(16bits)-per-block".     the XYZ used below is usually a value of 1 except in cases where the h/w designers have     combined two flash chips side-by-side (interleaved) instead of sequentially in the     address space. In the interleaved mode a 32bit value is retrieved by the h/w     by accessing 16bits from one chip and the other 16bits from the second chip.     On the other hand, in a sequential flash design, a 32bit value is retrieved     by the h/w by accessing 16bits from a flash chip and then incrementing to the     next location within that same flash chip to get the second 16bits. In both     cases it is all seamless to the s/w since the h/w SDRAM controller is performing     all the necessary accesses to reference the 32bit value. The one area that is     not seamless to the s/w, however, is the erase-block size. In interleaved designs     the s/w needs to be aware that the minimum number of bytes that can be erased     at any one time is *twice* the minimum for each individual chip. Hence the XYZ     modifier below to help manage that.  */  XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,  XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000,   XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000, XYZ*0x20000};// -----------------------// Note:// All these arrays defined so that we can have// the one we need at runtime when we've detected// the actual chip type present on the board.// -----------------------#define TOTAL_SECT (NUM_SEQUENTIAL_CHIPS*NUM_CHIP_SECT)static sect_info_t sect_info[TOTAL_SECT];     // Intel 28F160F3 Chips#define TOTAL_SECT_A (NUM_SEQUENTIAL_CHIPS*NUM_CHIP_SECT_A)static sect_info_t sect_info_A[TOTAL_SECT_A]; // Intel 28F320 Chips#define TOTAL_SECT_B (NUM_SEQUENTIAL_CHIPS*NUM_CHIP_SECT_B)static sect_info_t sect_info_B[TOTAL_SECT_B]; // Intel 28F128J3A Chips// -----------------------// Note:// After detecting the chip type at runtime we'll point this// at the specific array that pertains. (ie. at sect_info[]// or sect_info_B[] or ...)// -----------------------static sect_info_t *SectInfoTable;  // See note above.#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS// This block became necessary for supporting XIP downloads// on these style boards.static unsigned long *Cached_flash_addr;static unsigned short Cached_Short_valid;static unsigned short Cached_Short;#endif/****************************** Routine: Description:******************************/static void enable_read_mode(unsigned short *block_addr){#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS  #define READ_MODE_CODE 0x00ff00ff  unsigned long *addr;  addr = (unsigned long *)((unsigned long)block_addr&0xffffffc);  *addr = READ_MODE_CODE;#else  #define READ_MODE_CODE 0x00ff  *block_addr = READ_MODE_CODE;#endif}/****************************** Routine: Description:******************************/int read_device_codes(unsigned long *Code){  #define DEV_ID_CODE 0x0090  unsigned short regval;  unsigned short *block_addr = (unsigned short *)BSPCONF_FLASH_BASE;  *block_addr = DEV_ID_CODE;  regval = *block_addr;  *Code = (unsigned int)regval;  *Code = (unsigned int) (regval << 16);#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS  // Incrementing block_addr by one would take us  // into the second flash chip. Incrementing by two  // allows us to pick up the next 16bit value from  // the same chip we got the first 16bit value from.  regval = *(block_addr+2);#else    regval = *(block_addr+1);#endif  *Code = *Code | (regval);  enable_read_mode(block_addr);  return 1;}/****************************** Routine: Description: returns true if chip supports CFI.  array elements from CFI_START_ADDR to CFI_END_ADDR filled with CFI read array data. Returns false if chip doesn't support CFI.******************************/int read_cfi_array(unsigned short array[], int array_size){        return(0);}/****************************** Routine: Description: returns number of sectors if chip supports CFI.   sector_map contains size of each sector. Returns false if chip doesn't support CFI. WARNING: the generated sector may not be ordered correctly******************************/int build_sector_map(unsigned long sector_map[], int sector_map_size){        return(0);}/****************************** Routine: Description:******************************/static void clear_status(unsigned short *block_addr){#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS  #define CLEAR_CODE 0x00500050;  unsigned long *addr;  addr = (unsigned long *)((unsigned long)block_addr&0xfffffffc);  *addr = CLEAR_CODE;#else  #define CLEAR_CODE 0x50;  *block_addr = CLEAR_CODE;#endif  }/****************************** Routine: Description:******************************/static unsigned short read_status(unsigned short *block_addr){#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS  #define STATUS_CODE 0x00700070  unsigned long  l_status;  unsigned short status;  unsigned long *addr;  addr = (unsigned long *)((unsigned long)block_addr&0xfffffffc);  *addr = STATUS_CODE;  l_status = *addr;  // Next, take the upper 16bits and OR it with the  // lower 16bits forming a single 16bit return value.  status = (unsigned short)(l_status & 0x0000ffff);  status = status | (unsigned short)(l_status >> 16);  return status;#else  #define STATUS_CODE 0x70  unsigned short status;  *block_addr = STATUS_CODE;  status = *block_addr;  // util_printf("status read = %x\n",status); // *debug* temp  return status;#endif}/****************************** Routine: Description:******************************/static int is_busy(unsigned short *block_addr){#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS  #define STATUS_CODE 0x00700070  #define BUSY_BIT_POS 0x00800080  unsigned long status;  unsigned long *addr;  addr = (unsigned long *)((unsigned long)block_addr&0xfffffffc);  *addr = STATUS_CODE;  status = *addr;  if ((status & BUSY_BIT_POS) != BUSY_BIT_POS) {    // at least one of the bits is a zero indicating at    // at least one of the chips is busy.    return TRUE;  }  else {    return FALSE;  }#else    #define BUSY_BIT_POS 0x0080  unsigned short status;  status = read_status(block_addr);  if (0 == (BUSY_BIT_POS & status)) {    return TRUE;  }  else {    return FALSE;  }#endif  }/****************************** Routine: Description:******************************/static int was_error(unsigned short *block_addr){  #define ERASE_STATUS_BIT_POS      0x20  #define PROG_STATUS_BIT_POS       0x10  #define VOLT_STATUS_BIT_POS       0x08  #define PROG_SUSP_STATUS_BIT_POS  0x04  #define WRITE_PROT_STATUS_BIT_POS 0x02  unsigned short status;  unsigned char mask;  mask = 0;  mask |= WRITE_PROT_STATUS_BIT_POS;  mask |= PROG_SUSP_STATUS_BIT_POS;  mask |= VOLT_STATUS_BIT_POS;  mask |= PROG_STATUS_BIT_POS;  mask |= ERASE_STATUS_BIT_POS;  status = read_status(block_addr);  if (0 == (status & mask)) {    return 0;   // no errors.  }  else {    return status; // errors.  }}/****************************** Routine: Description:******************************/static int block_erase(unsigned short *block_addr){#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS  #define BLOCK_ERASE_CODE   0x00200020;  #define ERASE_CONFIRM_CODE 0x00D000D0;#else  #define BLOCK_ERASE_CODE   0x20;  #define ERASE_CONFIRM_CODE 0xD0;#endif  unsigned short status;  unsigned long *l_addr;  unsigned int retry_tally = 0;  l_addr = (unsigned long *)((unsigned long)block_addr&0xfffffffc);retry:    clear_status(block_addr);  if (0xBEEFFEED != FlashLockMode) {    util_printf("Error: Please Unlock Flash before trying to modify it.\n");    util_printf("       Giving up.\n");    return 1; // failed  }#ifdef TWO_16BIT_FLASH_CHIPS_INVOLVED_IN_EACH_32BIT_ACCESS  *l_addr = BLOCK_ERASE_CODE;  *l_addr = ERASE_CONFIRM_CODE;#else  *block_addr = BLOCK_ERASE_CODE;  *block_addr = ERASE_CONFIRM_CODE;#endif  while (is_busy(block_addr)) {}  if (was_error(block_addr)) {    status = read_status(block_addr);    util_printf("Erase error. block addr = 0x%X, status = 0x%x\n",block_addr,status);    util_printf("[retrying]\n");

⌨️ 快捷键说明

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