# HG changeset patch # User Mychaela Falconia # Date 1446332540 0 # Node ID 1db4da08b9b4568c943134990a9ebc92227fd169 # Parent 631fb20ff8d4cf5acf0aeff0aaed1b36bba1f973 gsm-fw/services/ffs/intelsbdrv.c: initial import from TCS211 source diff -r 631fb20ff8d4 -r 1db4da08b9b4 gsm-fw/services/ffs/intelsbdrv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/intelsbdrv.c Sat Oct 31 23:02:20 2015 +0000 @@ -0,0 +1,248 @@ +/****************************************************************************** + * Flash File System (ffs) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * FFS AMD single bank low level flash driver RAM code + * + * $Id: intelsbdrv.c 1.13 Thu, 08 Jan 2004 15:05:23 +0100 tsj $ + * + ******************************************************************************/ + +#include "ffs.cfg" + +#include "ffs/ffs.h" +#include "ffs/board/drv.h" +#include "ffs/board/ffstrace.h" + + +#define INTEL_UNLOCK_SLOW 1 + + +#undef tlw +#define tlw(contents) +#undef ttw +#define ttw(contents) + +// Status bits for Intel flash memory devices +#define INTEL_STATE_MACHINE_DONE (1<<7) +#define FLASH_READ(addr) (*(volatile uint16 *) (addr)) +#define FLASH_WRITE(addr, data) (*(volatile uint16 *) (addr)) = data + +asm(" .label _ffsdrv_ram_intel_begin"); +asm(" .def _ffsdrv_ram_intel_begin"); + +uint32 intel_int_disable(void); +void intel_int_enable(uint32 tmp); + +/****************************************************************************** + * INTEL Single Bank Driver Functions + ******************************************************************************/ +// Actually we should have disabled and enable the interrupts in this +// function, but when the interrupt functions are used Target don't run! +// Anyway, currently the interrupts are already disabled at this point thus +// it does not cause any problems. +int ffsdrv_ram_intel_sb_init(void) +{ + uint32 cpsr, i; + volatile char *addr; + uint16 status; + + for (i = 0; i < dev.numblocks; i++) + { + addr = block2addr(i); + + *addr = 0x50; // Intel Clear Status Register + *addr = 0xFF; // Intel read array + + *addr = 0x60; // Intel Config Setup + *addr = 0xD0; // Intel Unlock Block + + // Wait for unlock to finish + do { + status = FLASH_READ(addr); + } while (!(status & INTEL_STATE_MACHINE_DONE)); + + *addr = 0x70; // Intel Read Status Register + status = FLASH_READ(addr); + + // Is there an erase suspended? + if ((status & 0x40) != 0) { + *addr = 0xD0; // Intel erase resume + + *addr = 0x70; // Intel Read Status Register + // wait for erase to finish + do { + status = FLASH_READ(addr); + } while (!(status & INTEL_STATE_MACHINE_DONE)); + } + + *addr = 0xFF; // Intel Read Array + } + + return 0; +} + +void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value) +{ + uint32 cpsr; + + ttw(ttr(TTrDrv, "wh(%x,%x)" NL, addr, value)); + + if (~*addr & value) { + ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value)); + return; + } + + cpsr = intel_int_disable(); + tlw(led_on(LED_WRITE)); + +#if (INTEL_UNLOCK_SLOW == 1) + *addr = 0x60; // Intel Config Setup + *addr = 0xD0; // Intel Unlock Block +#endif + + *addr = 0x50; // Intel Clear Status Register + *addr = 0x40; // Intel program byte/word + *addr = value; + while ((*addr & 0x80) == 0) + ; + *addr = 0xFF; // Intel read array + tlw(led_off(LED_WRITE)); + intel_int_enable(cpsr); +} + +void ffsdrv_ram_intel_sb_erase(uint8 block) +{ + volatile char *addr; + uint32 cpsr; + uint16 poll; + + ttw(ttr(TTrDrvEra, "e(%d)" NL, block)); + + addr = block2addr(block); + + cpsr = intel_int_disable(); + tlw(led_on(LED_ERASE)); + +#if (INTEL_UNLOCK_SLOW == 1) + *addr = 0x60; // Intel Config Setup + *addr = 0xD0; // Intel Unlock Block +#endif + + *addr = 0x50; // Intel Clear Status Register + *addr = 0x20; // Intel Erase Setup + *addr = 0xD0; // Intel Erase Confirm + *addr = 0x70; // Intel Read Status Register + + // Wait for erase to finish. + while ((*addr & 0x80) == 0) { + tlw(led_toggle(LED_ERASE)); + // Poll interrupts, taking interrupt mask into account. + if (INT_REQUESTED) + { + // 1. suspend erase + // 2. enable interrupts + // .. now the interrupt code executes + // 3. disable interrupts + // 4. resume erase + + tlw(led_on(LED_ERASE_SUSPEND)); + + *addr = 0xB0; // Intel Erase Suspend + *addr = 0x70; // Intel Read Status Register + while (((poll = *addr) & 0x80) == 0) + ; + + // If erase is complete, exit immediately + if ((poll & 0x40) == 0) + break; + + *addr = 0xFF; // Intel read array + + tlw(led_off(LED_ERASE_SUSPEND)); + intel_int_enable(cpsr); + + // Other interrupts and tasks run now... + + cpsr = intel_int_disable(); + tlw(led_on(LED_ERASE_SUSPEND)); + + *addr = 0xD0; // Intel erase resume +// The following "extra" Read Status command is required because Intel has +// changed the specification of the W30 flash! (See "1.8 Volt Intel® +// Wireless Flash Memory with 3 Volt I/O 28F6408W30, 28F640W30, 28F320W30 +// Specification Update") + *addr = 0x70; // Intel Read Status Register + + tlw(led_off(LED_ERASE_SUSPEND)); + } + } + *addr = 0xFF; // Intel read array + + tlw(led_on(LED_ERASE)); + tlw(led_off(LED_ERASE)); + intel_int_enable(cpsr); +} + +// TODO: remove below function, not in use anymore. +void ffsdrv_ram_intel_erase(uint8 block) +{ + uint32 cpsr; + uint16 status; + + ttw(ttr(TTrDrvErase, "e(%d)" NL, block)); + tlw(led_on(LED_ERASE)); + + dev.addr = (uint16 *) block2addr(block); + + cpsr = intel_int_disable(); + dev.state = DEV_ERASE; + + *dev.addr = 0x60; // Intel Config setup + *dev.addr = 0xD0; // Intel Unlock block + + *dev.addr = 0x50; // Intel clear status register (not really necessary) + *dev.addr = 0x20; // Intel erase setup + *dev.addr = 0xD0; // Intel erase confirm + + intel_int_enable(cpsr); + + while ((*dev.addr & 0x80) == 0) + ; + + *dev.addr = 0xFF; // Intel read array + dev.state = DEV_READ; + tlw(led_off(LED_WRITE)); +} + + +/****************************************************************************** + * Interrupt Enable/Disable + ******************************************************************************/ + +uint32 intel_int_disable(void) +{ + asm(" .state16"); + asm(" mov A1, #0xC0"); + asm(" ldr A2, tct_intel_disable"); + asm(" bx A2 "); + + asm("tct_intel_disable .field _TCT_Control_Interrupts+0,32"); + asm(" .global _TCT_Control_Interrupts"); +} + +void intel_int_enable(uint32 cpsr) +{ + asm(" .state16"); + asm(" ldr A2, tct_intel_enable"); + asm(" bx A2 "); + + asm("tct_intel_enable .field _TCT_Control_Interrupts+0,32"); + asm(" .global _TCT_Control_Interrupts"); +} + +// Even though we have this end label, we cannot determine the number of +// constant/PC-relative data following the code! +asm(" .state32"); +asm(" .label _ffsdrv_ram_intel_end"); +asm(" .def _ffsdrv_ram_intel_end");