/*----------------------------------------------------------------------------- * * (c) Tardis Mobile - 2000 * * Name: flash.c * * Author: A Simpkins * * Date: 04 October * *----------------------------------------------------------------------------- * * Modification history: * * --- 14/08/2001 002 - converted to eCos * 04/10/2000 001 - Initial functions to test FLASH; flashEraseSegment & * flashWrite. * * *----------------------------------------------------------------------------- */ #include /* All the kernel specific stuff */ #include #include #include #if CYGHWR_HAL_ARM_TARDIS3_VERSION == 1 /* FLASH addresses corrected for address line error on hardware */ struct flashEscape flashDeviceInfoSeq = { 0x03, { (startAddressFLASH + (0x00001554)), 0x00aa, (startAddressFLASH + (0x00000aaa)), 0x0055, (startAddressFLASH + (0x00001554)), 0x0090 } }; struct flashEscape flashEraseSectorSeq = { 0x05, { (startAddressFLASH + 0x00001554), 0x00aa, (startAddressFLASH + 0x00000aaa), 0x0055, (startAddressFLASH + 0x00001554), 0x0080, (startAddressFLASH + 0x00001554), 0x00aa, (startAddressFLASH + 0x00000aaa), 0x0055 } }; struct flashEscape flashWriteSeq = { 0x03, { (startAddressFLASH + 0x00001554), 0x00aa, (startAddressFLASH + 0x00000aaa), 0x0055, (startAddressFLASH + 0x00001554), 0x00A0 } }; struct flashEscape flashEraseAllSeq = { 0x06, { (startAddressFLASH + 0x00001554), 0x00aa, (startAddressFLASH + 0x00000aaa), 0x0055, (startAddressFLASH + 0x00001554), 0x0080, (startAddressFLASH + 0x00001554), 0x00aa, (startAddressFLASH + 0x00000aaa), 0x0055, (startAddressFLASH + 0x00001554), 0x0010 } }; #else /* FLASH address values from AMD datasheet NOTE : addresses are for 8-bit access data is for 16-bit access all other combinations do not work! */ struct flashEscape flashDeviceInfoSeq = { 0x03, { (startAddressFLASH + 0x00000aaa), 0xaa, (startAddressFLASH + 0x00000555), 0x55, (startAddressFLASH + 0x00000aaa), 0x90 } }; struct flashEscape flashEraseSectorSeq = { 0x05, { (startAddressFLASH + 0x00000aaa), 0xaa, (startAddressFLASH + 0x00000555), 0x55, (startAddressFLASH + 0x00000aaa), 0x80, (startAddressFLASH + 0x00000aaa), 0xaa, (startAddressFLASH + 0x00000555), 0x55 } }; struct flashEscape flashWriteSeq = { 0x03, { (startAddressFLASH + 0x00000aaa), 0xaa, (startAddressFLASH + 0x00000555), 0x55, (startAddressFLASH + 0x00000aaa), 0xA0 } }; struct flashEscape flashEraseAllSeq = { 0x06, { (startAddressFLASH + 0x00000aaa), 0xaa, (startAddressFLASH + 0x00000555), 0x55, (startAddressFLASH + 0x00000aaa), 0x80, (startAddressFLASH + 0x00000aaa), 0xaa, (startAddressFLASH + 0x00000555), 0x55, (startAddressFLASH + 0x00000aaa), 0x10 } }; #endif void __attribute__ ((section (".2ram.playFlashEscapeSeq"))) playFlashEscapeSeq (struct flashEscape *sequence) { volatile cyg_uint16 *pMem; for (cyg_uint16 count = 0; count < sequence->length; count++) { pMem = (cyg_uint16* )sequence->flashpair[count].pairAddress; *pMem = sequence->flashpair[count].pairData; } } void __attribute__ ((section (".2ram.flashReset"))) flashReset(void) { volatile cyg_uint16 *pMem; pMem = (cyg_uint16 *)startAddressFLASH; *pMem = flash_reset; } cyg_uint32 __attribute__ ((section (".2ram.flash_query"))) flash_query(cyg_uint32 *callAddr) { flashcmd *data = (flashcmd *)callAddr; bool cacheOn = false; switch (data->flashCommand) { // Read the FLASH device information case flashCmd_Info: int old; HAL_DISABLE_INTERRUPTS(old); // disable interrupts if (ASIC_CACHE_EN == 0x0001) { cacheOn = true; ASIC_CACHE_EN = 0x0000; // dissable cache } flashReset(); playFlashEscapeSeq(&flashDeviceInfoSeq); volatile cyg_uint16 *pMem; pMem =(cyg_uint16 *)flash_make; ((infoFlashCmd *)data)->make = *pMem; flashReset(); playFlashEscapeSeq(&flashDeviceInfoSeq); pMem =(cyg_uint16 *)flash_deviceID; ((infoFlashCmd *)data)->deviceID = *pMem; flashReset(); if (cacheOn) ASIC_CACHE_EN = 0x0001; // re-enable cache HAL_RESTORE_INTERRUPTS(old); // re-enable interrupts break; // Erase the specified sector // Erasing sectors on a FLASH device may take a while. Because we can not run code from the // FLASH during this time, we should dissable interrupts. Whilst we poll the FLASH to see if // the opoeration has compleated we should also poll the interrupt status, is an interrupt has // occured then we should suspend the FLASH oporation, enable (thus handle) interrupts before case flashCmd_Erase: { int old; HAL_DISABLE_INTERRUPTS(old); // disable interrupts if (ASIC_CACHE_EN == 0x0001) { cacheOn = true; ASIC_CACHE_EN = 0x0000; // dissable cache } ((eraseFlashCmd *)data)->onHold = false; flashReset(); playFlashEscapeSeq(&flashEraseSectorSeq); volatile cyg_uint16 *pMem; pMem = (cyg_uint16 *)((eraseFlashCmd *)data)->sectorNo; *pMem = flash_eraseSectorCmd; while ((*pMem & flash_DQ7) == 0) { // ### fix me // what about a timeout - i.e. if the FLASH never finishes erasing the sector? // check to see if an interrupt has occured if (ASIC_INTREG & SiRFIRQ != 0) { *pMem = 0xB0; // Suspend erase ((eraseFlashCmd *)data)->onHold = true; // flag erase incompleate break; // terminate the while loop } } if (((eraseFlashCmd *)data)->onHold == true) { // on hold so not compleated ((eraseFlashCmd *)data)->success = false; } else { // we have compleated signal this and reset FLASH ((eraseFlashCmd *)data)->success = true; flashReset(); } if (cacheOn) ASIC_CACHE_EN = 0x0001; // re-enable cache HAL_RESTORE_INTERRUPTS(old); // re-enable interrupts break; } case flashCmd_ResumeErase: { int old; HAL_DISABLE_INTERRUPTS(old); // disable interrupts if (ASIC_CACHE_EN == 0x0001) { cacheOn = true; ASIC_CACHE_EN = 0x0000; // dissable cache } volatile cyg_uint16 *pMem; pMem = (cyg_uint16 *)((eraseFlashCmd *)data)->sectorNo; *pMem = 0x30; // continue erasing FLASH ((eraseFlashCmd *)data)->onHold = false; while ((*pMem & flash_DQ7) == 0) { // ### fix me // what about a timeout - i.e. if the FLASH never finishes erasing the sector? // check to see if an interrupt has occured if (ASIC_INTREG & SiRFIRQ != 0) { *pMem = 0xB0; // Suspend erase ((eraseFlashCmd *)data)->onHold = true; // flag suspended break; // terminate the while loop } } if (((eraseFlashCmd *)data)->onHold) { ((eraseFlashCmd *)data)->success = false; } else { ((eraseFlashCmd *)data)->success = true; flashReset(); } if (cacheOn) ASIC_CACHE_EN = 0x0001; // re-enable cache HAL_RESTORE_INTERRUPTS(old); // re-enable interrupts break; } case flashCmd_Write: { // test for bad address (we can only program 16 bit data at an even address) if (((writeFlashCmd *)data)->writeAddress % 2 == 1 ) { ((writeFlashCmd *)data)->result = flashResult_badAddress; } else { int old; HAL_DISABLE_INTERRUPTS(old); // disable interrupts if (ASIC_CACHE_EN == 0x0001) { cacheOn = true; ASIC_CACHE_EN = 0x0000; // dissable cache } flashReset(); playFlashEscapeSeq(&flashWriteSeq); volatile cyg_uint16 *pMem; pMem = (cyg_uint16 *)((writeFlashCmd *)data)->writeAddress; cyg_uint16 writeChar = ((writeFlashCmd *)data)->writeData; *pMem = writeChar; while ( (*pMem & flash_DQ7) != (writeChar & flash_DQ7) ) { // ### fix me // what about a timeout - i.e. if the FLASH never finishes programming? } flashReset(); if (cacheOn) ASIC_CACHE_EN = 0x0001; // re-enable cache HAL_RESTORE_INTERRUPTS(old); // re-enable interrupts ((writeFlashCmd *)data)->result = flashResult_OK; } break; } default: break; } return 1; }