📄 flashdrv.c
字号:
/* flashdrv.c - FLASH memory functions and definitions*//* Copyright Galileo Technology. *//*DESCRIPTIONThis flash driver gives the user a convenient interface to FLASH memory locatedon the user`s board, it supports various layout configurations such as:1. One pure 8 bit device (Such as AMD`s AM29LV040B).2. 1,2,4 or 8 devices 16 bit wide configured to operate in 8 bit mode.3. 1,2 or 4 devices each 16 bit wide.Before using the driver you must call the initialization function at least onceor when ever you are changing the FLASH base address.The list bellow contains the supported FLASH memory devices, new devices can beadded easily in the future.*//*includes*/#ifdef __linux__#include <asm/galileo-boards/evb64120A/flashdrv.h>#else#include "flashdrv.h"#endif/* locals */#ifdef __MIPSEB__ // skranz, add#define BE // skranz, add#endif // skranz, add/******************************************************************************* Those two tables contain the supported flash devices information needed by* the driver: * The first table "flashParametrs" starts with 10 shared fields * (currently 6 are reserved):* index 0 => Pointer to an entry in the second table list* index 1 => baseAddress - Flash memory device base address.* index 2 => width - 1, 2, 4 or 8 Bytes. * index 3 => mode - PURE8, X8 or X16 flash configuration (for X16 devices only)* The second table (flashTypes) contains: * Entry`s structure:* Manufacture ID,Device ID,number of sectors,list of sector`s sizes* (in Kbytes starting with sector number 0).* The end of the list is pointed with a zero.******************************************************************************/unsigned int flashParametrs[10]; /* 0 Entry pointer */ /* 0 Base address */ /* 0 Width */ /* 0 Mode */ /* 0,0,0,0,0,0, spare entries. */unsigned int flashTypes[] = { /* 0 */ AMD_FLASH, AM29F400BB, 11, 16, 8, 8, 32, 64, 64, 64, 64, 64, 64, 64, /* 1 */ AMD_FLASH, AM29F400BT, 11, 64, 64, 64, 64, 64, 64, 64, 32, 8, 8, 16, /* 2 */ ST_FLASH, M29W040, 8, 64, 64, 64, 64, 64, 64, 64, 64, /* 3 */ AMD_FLASH, AM29LV040B, 8, 64, 64, 64, 64, 64, 64, 64, 64, /* 4 */ AMD_FLASH, AM29LV800BT, 19, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 32, 8, 8, 16, /* 5 */ INTEL_FLASH, I28F320J3A, 32, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, /* 6 */ INTEL_FLASH, I28F640J3A, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, /* 7 */ INTEL_FLASH, I28F128J3A, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, /* 8 */ AMD_FLASH, AM29LV400BB, 11, 16, 8, 8, 32, 64, 64, 64, 64, 64, 64, 64, /* 9 */ AMD_FLASH, AM29LV400BT, 11, 64, 64, 64, 64, 64, 64, 64, 32, 8, 8, 16, /* 10 */ INTEL_FLASH, I28F320B3_T, 71, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 8, 8, 8, 8, 8, 8, 8, 8, /* 11 */ INTEL_FLASH, I28F320B3_B, 71, 8, 8, 8, 8, 8, 8, 8, 8, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, /* 12 */ INTEL_FLASH, I28F160B3_B, 39, 8, 8, 8, 8, 8, 8, 8, 8, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, /* 13 */ INTEL_FLASH, I28F160B3_T, 39, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 8, 8, 8, 8, 8, 8, 8, 8, 0 /* End of list indicator */};/********************************************************************* flashInit - Initializes the FLASH memory driver`s parameters, this function * must be called at least once before using the FLASH memory.* If you are changing the FLASH base address call this function* again.** INPUTS: unsigned int flashBaseAddress - The flash base Address.* unsigned int flashWidth - Flash bus width in Bytes: 1,2,4 or 8.* flashMode - PURE8, X8 or X16. * RETURNS: Flash Size, zero when operation (flashInit) failed.*********************************************************************/unsigned int flashInit(unsigned int flashBaseAddress, unsigned int flashWidth, FLASHmode flashMode){ unsigned short mfrId = 0; unsigned short devId = 0xffff; unsigned int FirstAddr, SecondAddr, ThirdAddr; unsigned int pArray = 0; unsigned int counter; unsigned int flashSize = 0; /* update the list with relevant parametrs */ flashParametrs[0] = 0; /* Default initialization */ flashParametrs[1] = flashBaseAddress; flashParametrs[2] = flashWidth; flashParametrs[3] = flashMode; /* Get the FLASH`s ID */ switch (FLASH_WIDTH) { case 1: /* AMD or ST ?? * */ if (flashMode == PURE8) { /* Boot Flash */ FirstAddr = 0x5555; SecondAddr = 0x2aaa; ThirdAddr = 0x5555; } else { /* X16 device configured to 8bit Mode */ FirstAddr = 0xaaaa; SecondAddr = 0x5555; ThirdAddr = 0xaaaa; } flashReset(); WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xAA); WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0x90); READ_CHAR(FLASH_BASE_ADDRESS + 0x0, &mfrId); if (mfrId == AMD_FLASH || mfrId == ST_FLASH) { flashReset(); WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xAA); WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0x90); READ_CHAR(FLASH_BASE_ADDRESS + 0x1, &devId); break; } /* Micron or Intel ?? * */ WRITE_CHAR(FLASH_BASE_ADDRESS, 0xff); /* Read Array */ /* Flash reset for Intel/Micron */ WRITE_CHAR(FLASH_BASE_ADDRESS, 0x90); /* IDENTIFY Device */ READ_CHAR(FLASH_BASE_ADDRESS + 0x0, &mfrId); /*Address for ManufactureID */ if (mfrId == INTEL_FLASH || mfrId == MICRON_FLASH) { WRITE_CHAR(FLASH_BASE_ADDRESS, 0xff); /* Read Array */ /*Flash reset for Intel/Micron */ WRITE_CHAR(FLASH_BASE_ADDRESS, 0x90); /* IDENTIFY Device */ READ_CHAR(FLASH_BASE_ADDRESS + 0x1, &devId); /*Address for DeviceID */ } break; case 2: case 4: case 8: /* AMD or ST ??? */ flashReset(); WRITE_SHORT(FLASH_BASE_ADDRESS + 0x5555 * FLASH_WIDTH, 0xaa); WRITE_SHORT(FLASH_BASE_ADDRESS + 0x2aaa * FLASH_WIDTH, 0x55); WRITE_SHORT(FLASH_BASE_ADDRESS + 0x5555 * FLASH_WIDTH, 0x90); READ_SHORT(FLASH_BASE_ADDRESS, &mfrId); flashReset(); /* Read the device ID */ if (mfrId == AMD_FLASH || mfrId == ST_FLASH) { WRITE_SHORT(FLASH_BASE_ADDRESS + 0x5555 * FLASH_WIDTH, 0xaa); WRITE_SHORT(FLASH_BASE_ADDRESS + 0x2aaa * FLASH_WIDTH, 0x55); WRITE_SHORT(FLASH_BASE_ADDRESS + 0x5555 * FLASH_WIDTH, 0x90); READ_SHORT(FLASH_BASE_ADDRESS + 0x1 * FLASH_WIDTH, &devId); break; } /* Micron or Intel ?? * */ WRITE_WORD(FLASH_BASE_ADDRESS, 0x00ff00ff); WRITE_WORD(FLASH_BASE_ADDRESS, 0x00900090); if ((FLASH_WIDTH == 4) || (FLASH_WIDTH == 8)) { /* 32 or 64 bit */ READ_SHORT(FLASH_BASE_ADDRESS, &mfrId); } else { /* FLASH_WIDTH = 2 */ READ_SHORT(FLASH_BASE_ADDRESS, &mfrId); } if ((mfrId == INTEL_FLASH) || (mfrId == MICRON_FLASH)) { /* Flash reset for Intel/Micron */ flashReset(); WRITE_WORD(FLASH_BASE_ADDRESS, 0x00ff00ff); WRITE_WORD(FLASH_BASE_ADDRESS, 0x00900090); READ_SHORT(FLASH_BASE_ADDRESS + 0x1 * FLASH_WIDTH, &devId); } break; } /* Try to locate the device in the supported flashes list (FLASH_TYPE). according to the keys: 1) mfrId - manufactor ID. 2) devId - device ID. */ while (true) { if (flashTypes[pArray] == 0) { flashReset(); return 0; /* Device not in the list */ } if ((flashTypes[pArray] == mfrId) && (flashTypes[pArray + 1] == devId)) { POINTER_TO_FLASH = pArray; for (counter = 0; counter < flashTypes[NUMBER_OF_SECTORS]; counter++) { flashSize = flashSize + flashTypes[FIRST_SECTOR_SIZE + counter]; } if (FLASH_MODE != PURE8) { flashReset(); return (flashSize * _1K * (FLASH_WIDTH / (FLASH_MODE / 8))); } else { flashReset(); return (flashSize * _1K * FLASH_WIDTH); } } pArray += (3 + flashTypes[pArray + 2]); /* Move to next entry */ }}/********************************************************************* flashReset - Resets the Flash memory (FLASH`s internal protocol reset).* * INTPUTS: N/A * OUTPUT: N/A *********************************************************************/void flashReset(){ unsigned char ucData; unsigned short usData; unsigned int uiData; if ((flashTypes[POINTER_TO_FLASH] == AMD_FLASH) || (flashTypes[POINTER_TO_FLASH]) == ST_FLASH) { if (FLASH_MODE == X16) { ucData = 0xf0; usData = 0xf0; uiData = 0x00f000f0; } else { /* case of PURE8 or X8 */ ucData = 0xf0; usData = 0xf0f0; uiData = 0xf0f0f0f0; } } else { if (FLASH_MODE == X16) { ucData = 0xff; usData = 0xff; uiData = 0x00ff00ff; } else { /* case of PURE8 or X8 */ ucData = 0xff; usData = 0xffff; uiData = 0xffffffff; } } switch (FLASH_WIDTH) { case 1: WRITE_CHAR(FLASH_BASE_ADDRESS, ucData); break; case 2: WRITE_SHORT(FLASH_BASE_ADDRESS, usData); break; case 4: WRITE_WORD(FLASH_BASE_ADDRESS, uiData); break; case 8: WRITE_WORD(FLASH_BASE_ADDRESS, uiData); WRITE_WORD(FLASH_BASE_ADDRESS + 0x4, uiData); break; }}/********************************************************************* flashErase - The function erases the WHOLE flash memory.*** RETURNS: true on success,false on failure*********************************************************************/bool flashErase(){ unsigned int totalFlashSize; unsigned int address; unsigned int readData; unsigned int nextSector; flashReset(); totalFlashSize = flashGetSize(); /* scan all flash memory space. */ address = 0; while (address < totalFlashSize) { readData = flashReadWord(address); if (readData != 0xffffffff) { /* offset with dirty data. */ flashEraseSector(flashInWhichSector(address)); nextSector = flashInWhichSector(address) + 1; if (nextSector < flashTypes[NUMBER_OF_SECTORS]) /* jump to next sector. */ address = flashGetSectorOffset(nextSector); else /* end of erasing. */ address = totalFlashSize; } else address += 4; } return true;}/********************************************************************* flashEraseSector - The function erases a specific sector in the flash memory.** INPUTS: Sector number.* RETURNS: true on success,false on failure.*********************************************************************/bool flashEraseSector(unsigned int sectorNumber){ volatile unsigned int spin; unsigned int regValue; unsigned int sectorBaseAddress = 0; unsigned int i; unsigned int data20, dataD0, data70; unsigned int dataPoll; unsigned int FirstAddr, SecondAddr, ThirdAddr, FourthAddr, FifthAddr; unsigned int FirstData, SecondData, ThirdData; unsigned int FourthData, FifthData, SixthData; /* calculate the sector base Address according to the following parametrs: 1: FLASH_WIDTH 2: the size of each sector which it detailed in the table */ /* checking the if the sectorNumber is legal. */ if (sectorNumber > flashTypes[NUMBER_OF_SECTORS] - 1) return false; /* now the calculation begining of the sector Address */ for (i = 0; i < sectorNumber; i++) { sectorBaseAddress = sectorBaseAddress + flashTypes[FIRST_SECTOR_SIZE + i]; } /* In case of X8 wide the address should be */ if (FLASH_MODE == PURE8) sectorBaseAddress = _1K * sectorBaseAddress; if (FLASH_MODE == X8) sectorBaseAddress = _1K * sectorBaseAddress; /* In case of X16 wide the address should be */ if (FLASH_MODE == X16)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -