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 |