FreeCalypso > hg > fc-tourmaline
comparison src/cs/drivers/drv_app/ffs/board/intelsbdrv.c @ 0:4e78acac3d88
src/{condat,cs,gpf,nucleus}: import from Selenite
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Fri, 16 Oct 2020 06:23:26 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:4e78acac3d88 |
|---|---|
| 1 /****************************************************************************** | |
| 2 * Flash File System (ffs) | |
| 3 * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com | |
| 4 * | |
| 5 * FFS AMD single bank low level flash driver RAM code | |
| 6 * | |
| 7 * $Id: intelsbdrv.c 1.13 Thu, 08 Jan 2004 15:05:23 +0100 tsj $ | |
| 8 * | |
| 9 ******************************************************************************/ | |
| 10 | |
| 11 #include "ffs.cfg" | |
| 12 | |
| 13 #include "ffs/ffs.h" | |
| 14 #include "ffs/board/drv.h" | |
| 15 #include "ffs/board/ffstrace.h" | |
| 16 | |
| 17 | |
| 18 #define INTEL_UNLOCK_SLOW 1 | |
| 19 | |
| 20 | |
| 21 #undef tlw | |
| 22 #define tlw(contents) | |
| 23 #undef ttw | |
| 24 #define ttw(contents) | |
| 25 | |
| 26 // Status bits for Intel flash memory devices | |
| 27 #define INTEL_STATE_MACHINE_DONE (1<<7) | |
| 28 #define FLASH_READ(addr) (*(volatile uint16 *) (addr)) | |
| 29 #define FLASH_WRITE(addr, data) (*(volatile uint16 *) (addr)) = data | |
| 30 | |
| 31 #ifdef __GNUC__ | |
| 32 asm(".globl ffsdrv_ram_intel_begin"); | |
| 33 asm("ffsdrv_ram_intel_begin:"); | |
| 34 #else | |
| 35 asm(" .label _ffsdrv_ram_intel_begin"); | |
| 36 asm(" .def _ffsdrv_ram_intel_begin"); | |
| 37 #endif | |
| 38 | |
| 39 uint32 intel_int_disable(void); | |
| 40 void intel_int_enable(uint32 tmp); | |
| 41 | |
| 42 /****************************************************************************** | |
| 43 * INTEL Single Bank Driver Functions | |
| 44 ******************************************************************************/ | |
| 45 // Actually we should have disabled and enable the interrupts in this | |
| 46 // function, but when the interrupt functions are used Target don't run! | |
| 47 // Anyway, currently the interrupts are already disabled at this point thus | |
| 48 // it does not cause any problems. | |
| 49 int ffsdrv_ram_intel_sb_init(void) | |
| 50 { | |
| 51 uint32 cpsr, i; | |
| 52 volatile char *addr; | |
| 53 uint16 status; | |
| 54 | |
| 55 for (i = 0; i < dev.numblocks; i++) | |
| 56 { | |
| 57 addr = block2addr(i); | |
| 58 | |
| 59 *addr = 0x50; // Intel Clear Status Register | |
| 60 *addr = 0xFF; // Intel read array | |
| 61 | |
| 62 *addr = 0x60; // Intel Config Setup | |
| 63 *addr = 0xD0; // Intel Unlock Block | |
| 64 | |
| 65 // Wait for unlock to finish | |
| 66 do { | |
| 67 status = FLASH_READ(addr); | |
| 68 } while (!(status & INTEL_STATE_MACHINE_DONE)); | |
| 69 | |
| 70 *addr = 0x70; // Intel Read Status Register | |
| 71 status = FLASH_READ(addr); | |
| 72 | |
| 73 // Is there an erase suspended? | |
| 74 if ((status & 0x40) != 0) { | |
| 75 *addr = 0xD0; // Intel erase resume | |
| 76 | |
| 77 *addr = 0x70; // Intel Read Status Register | |
| 78 // wait for erase to finish | |
| 79 do { | |
| 80 status = FLASH_READ(addr); | |
| 81 } while (!(status & INTEL_STATE_MACHINE_DONE)); | |
| 82 } | |
| 83 | |
| 84 *addr = 0xFF; // Intel Read Array | |
| 85 } | |
| 86 | |
| 87 return 0; | |
| 88 } | |
| 89 | |
| 90 void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value) | |
| 91 { | |
| 92 uint32 cpsr; | |
| 93 | |
| 94 ttw(ttr(TTrDrv, "wh(%x,%x)" NL, addr, value)); | |
| 95 | |
| 96 if (~*addr & value) { | |
| 97 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value)); | |
| 98 return; | |
| 99 } | |
| 100 | |
| 101 cpsr = intel_int_disable(); | |
| 102 tlw(led_on(LED_WRITE)); | |
| 103 | |
| 104 #if (INTEL_UNLOCK_SLOW == 1) | |
| 105 *addr = 0x60; // Intel Config Setup | |
| 106 *addr = 0xD0; // Intel Unlock Block | |
| 107 #endif | |
| 108 | |
| 109 *addr = 0x50; // Intel Clear Status Register | |
| 110 *addr = 0x40; // Intel program byte/word | |
| 111 *addr = value; | |
| 112 while ((*addr & 0x80) == 0) | |
| 113 ; | |
| 114 *addr = 0xFF; // Intel read array | |
| 115 tlw(led_off(LED_WRITE)); | |
| 116 intel_int_enable(cpsr); | |
| 117 } | |
| 118 | |
| 119 void ffsdrv_ram_intel_sb_erase(uint8 block) | |
| 120 { | |
| 121 volatile char *addr; | |
| 122 uint32 cpsr; | |
| 123 uint16 poll; | |
| 124 | |
| 125 ttw(ttr(TTrDrvEra, "e(%d)" NL, block)); | |
| 126 | |
| 127 addr = block2addr(block); | |
| 128 | |
| 129 cpsr = intel_int_disable(); | |
| 130 tlw(led_on(LED_ERASE)); | |
| 131 | |
| 132 #if (INTEL_UNLOCK_SLOW == 1) | |
| 133 *addr = 0x60; // Intel Config Setup | |
| 134 *addr = 0xD0; // Intel Unlock Block | |
| 135 #endif | |
| 136 | |
| 137 *addr = 0x50; // Intel Clear Status Register | |
| 138 *addr = 0x20; // Intel Erase Setup | |
| 139 *addr = 0xD0; // Intel Erase Confirm | |
| 140 *addr = 0x70; // Intel Read Status Register | |
| 141 | |
| 142 // Wait for erase to finish. | |
| 143 while ((*addr & 0x80) == 0) { | |
| 144 tlw(led_toggle(LED_ERASE)); | |
| 145 // Poll interrupts, taking interrupt mask into account. | |
| 146 if (INT_REQUESTED) | |
| 147 { | |
| 148 // 1. suspend erase | |
| 149 // 2. enable interrupts | |
| 150 // .. now the interrupt code executes | |
| 151 // 3. disable interrupts | |
| 152 // 4. resume erase | |
| 153 | |
| 154 tlw(led_on(LED_ERASE_SUSPEND)); | |
| 155 | |
| 156 *addr = 0xB0; // Intel Erase Suspend | |
| 157 *addr = 0x70; // Intel Read Status Register | |
| 158 while (((poll = *addr) & 0x80) == 0) | |
| 159 ; | |
| 160 | |
| 161 // If erase is complete, exit immediately | |
| 162 if ((poll & 0x40) == 0) | |
| 163 break; | |
| 164 | |
| 165 *addr = 0xFF; // Intel read array | |
| 166 | |
| 167 tlw(led_off(LED_ERASE_SUSPEND)); | |
| 168 intel_int_enable(cpsr); | |
| 169 | |
| 170 // Other interrupts and tasks run now... | |
| 171 | |
| 172 cpsr = intel_int_disable(); | |
| 173 tlw(led_on(LED_ERASE_SUSPEND)); | |
| 174 | |
| 175 *addr = 0xD0; // Intel erase resume | |
| 176 // The following "extra" Read Status command is required because Intel has | |
| 177 // changed the specification of the W30 flash! (See "1.8 Volt Intel® | |
| 178 // Wireless Flash Memory with 3 Volt I/O 28F6408W30, 28F640W30, 28F320W30 | |
| 179 // Specification Update") | |
| 180 *addr = 0x70; // Intel Read Status Register | |
| 181 | |
| 182 tlw(led_off(LED_ERASE_SUSPEND)); | |
| 183 } | |
| 184 } | |
| 185 *addr = 0xFF; // Intel read array | |
| 186 | |
| 187 tlw(led_on(LED_ERASE)); | |
| 188 tlw(led_off(LED_ERASE)); | |
| 189 intel_int_enable(cpsr); | |
| 190 } | |
| 191 | |
| 192 // TODO: remove below function, not in use anymore. | |
| 193 void ffsdrv_ram_intel_erase(uint8 block) | |
| 194 { | |
| 195 uint32 cpsr; | |
| 196 uint16 status; | |
| 197 | |
| 198 ttw(ttr(TTrDrvErase, "e(%d)" NL, block)); | |
| 199 tlw(led_on(LED_ERASE)); | |
| 200 | |
| 201 dev.addr = (uint16 *) block2addr(block); | |
| 202 | |
| 203 cpsr = intel_int_disable(); | |
| 204 dev.state = DEV_ERASE; | |
| 205 | |
| 206 *dev.addr = 0x60; // Intel Config setup | |
| 207 *dev.addr = 0xD0; // Intel Unlock block | |
| 208 | |
| 209 *dev.addr = 0x50; // Intel clear status register (not really necessary) | |
| 210 *dev.addr = 0x20; // Intel erase setup | |
| 211 *dev.addr = 0xD0; // Intel erase confirm | |
| 212 | |
| 213 intel_int_enable(cpsr); | |
| 214 | |
| 215 while ((*dev.addr & 0x80) == 0) | |
| 216 ; | |
| 217 | |
| 218 *dev.addr = 0xFF; // Intel read array | |
| 219 dev.state = DEV_READ; | |
| 220 tlw(led_off(LED_WRITE)); | |
| 221 } | |
| 222 | |
| 223 | |
| 224 /****************************************************************************** | |
| 225 * Interrupt Enable/Disable | |
| 226 ******************************************************************************/ | |
| 227 | |
| 228 #ifdef __GNUC__ | |
| 229 #define NOINLINE __attribute__ ((noinline)) | |
| 230 #else | |
| 231 #define NOINLINE | |
| 232 #endif | |
| 233 | |
| 234 uint32 NOINLINE intel_int_disable(void) | |
| 235 { | |
| 236 #ifdef __GNUC__ | |
| 237 asm(" .code 16"); | |
| 238 #else | |
| 239 asm(" .state16"); | |
| 240 #endif | |
| 241 asm(" mov A1, #0xC0"); | |
| 242 asm(" ldr A2, tct_intel_disable"); | |
| 243 asm(" bx A2 "); | |
| 244 | |
| 245 #ifdef __GNUC__ | |
| 246 asm(".balign 4"); | |
| 247 asm("tct_intel_disable:"); | |
| 248 asm(" .word TCT_Control_Interrupts"); | |
| 249 #else | |
| 250 asm("tct_intel_disable .field _TCT_Control_Interrupts+0,32"); | |
| 251 asm(" .global _TCT_Control_Interrupts"); | |
| 252 #endif | |
| 253 } | |
| 254 | |
| 255 void NOINLINE intel_int_enable(uint32 cpsr) | |
| 256 { | |
| 257 #ifdef __GNUC__ | |
| 258 asm(" .code 16"); | |
| 259 #else | |
| 260 asm(" .state16"); | |
| 261 #endif | |
| 262 asm(" ldr A2, tct_intel_enable"); | |
| 263 asm(" bx A2 "); | |
| 264 | |
| 265 #ifdef __GNUC__ | |
| 266 asm(".balign 4"); | |
| 267 asm("tct_intel_enable:"); | |
| 268 asm(" .word TCT_Control_Interrupts"); | |
| 269 #else | |
| 270 asm("tct_intel_enable .field _TCT_Control_Interrupts+0,32"); | |
| 271 asm(" .global _TCT_Control_Interrupts"); | |
| 272 #endif | |
| 273 } | |
| 274 | |
| 275 // Even though we have this end label, we cannot determine the number of | |
| 276 // constant/PC-relative data following the code! | |
| 277 #ifdef __GNUC__ | |
| 278 asm(".globl ffsdrv_ram_intel_end"); | |
| 279 asm("ffsdrv_ram_intel_end:"); | |
| 280 #else | |
| 281 asm(" .state32"); | |
| 282 asm(" .label _ffsdrv_ram_intel_end"); | |
| 283 asm(" .def _ffsdrv_ram_intel_end"); | |
| 284 #endif |
