comparison services/ffs/drv.c @ 0:75a11d740a02

initial import of gsm-fw from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 00:02:41 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:75a11d740a02
1 /******************************************************************************
2 * Flash File System (ffs)
3 * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
4 *
5 * ffs low level flash driver
6 *
7 * $Id: drv.c 1.30.1.6.1.51.1.1.1.13.1.11 Tue, 06 Jan 2004 14:36:52 +0100 tsj $
8 *
9 ******************************************************************************/
10
11 #include "../../include/config.h"
12 #include "ffs.h"
13 #include "drv.h"
14 #include "core.h" /* for FFS_BLOCKS_MAX */
15 #include "ffstrace.h"
16 #include "intctl.h"
17 #include "ramffs.h"
18 #include <string.h>
19
20
21 /******************************************************************************
22 * "Block info" stupidity
23 ******************************************************************************/
24
25 static struct block_info_s block_info[FFS_BLOCKS_MAX];
26
27
28 /******************************************************************************
29 * Macros
30 ******************************************************************************/
31
32 #define addr2offset(address) ( (int) (address) - (int) dev.base )
33
34
35 /******************************************************************************
36 * Generic Driver Functions
37 ******************************************************************************/
38
39 // Note: This function is designed for little-endian memory addressing!
40 void ffsdrv_write_byte(void *dst, uint8 value)
41 {
42 uint16 halfword;
43
44 tw(tr(TR_FUNC, TrDrvWrite, "ffsdrv_write_byte(0x%05x, 0x%x)\n",
45 (int) (addr2offset(dst)), value));
46 ttw(str(TTrDrvWrite, "wb" NL));
47
48 if ((int) dst & 1)
49 halfword = (value << 8) | *((uint8 *) dst - 1);
50 else
51 halfword = (*((uint8 *) dst + 1) << 8) | (value);
52
53 ffsdrv.write_halfword((uint16 *) ((int) dst & ~1), halfword);
54 }
55
56 void ffsdrv_generic_write(void *dst, const void *src, uint16 size)
57 {
58 uint8 *mydst = dst;
59 const uint8 *mysrc = src;
60
61 if (size > 0)
62 {
63 if ((unsigned int) mydst & 1) {
64 ffsdrv_write_byte(mydst++, *mysrc++);
65 size--;
66 }
67 while (size >= 2) {
68 ffsdrv.write_halfword((uint16 *) mydst,
69 mysrc[0] | (mysrc[1] << 8));
70 size -= 2;
71 mysrc += 2;
72 mydst += 2;
73 }
74 if (size == 1)
75 ffsdrv_write_byte(mydst++, *mysrc++);
76 }
77 }
78
79 /******************************************************************************
80 * Dummy Functions
81 ******************************************************************************/
82
83 int ffsdrv_null_init(void)
84 {
85 ttw(ttr(TTrDrvOther, "ffsdrv_null_init()" NL));
86
87 return 0;
88 }
89
90 void ffsdrv_null_erase(uint8 block)
91 {
92 ttw(ttr(TTrDrvErase, "ffsdrv_null_erase(%d)" NL, block));
93 }
94
95 void ffsdrv_null_write_halfword(volatile uint16 *addr, uint16 value)
96 {
97 ttw(ttr(TTrDrvWrite, "ffsdrv_null_write_halfword(0x%x, 0x%x)" NL, addr, value));
98 }
99
100 void ffsdrv_null_write(void *dst, const void *src, uint16 size)
101 {
102 ttw(ttr(TTrDrvWrite, "ffsdrv_null_write(0x%x, 0x%x, %d)" NL, dst, src, size));
103 }
104
105 void ffsdrv_null_erase_suspend(void)
106 {
107 ttw(str(TTrDrvErase, "ffsdrv_null_erase_suspend()" NL));
108 }
109
110 void ffsdrv_null_erase_resume(void)
111 {
112 ttw(str(TTrDrvErase, "ffsdrv_null_erase_resume()" NL));
113 }
114
115 void ffsdrv_null_write_end(void)
116 {
117 ttw(str(TTrDrvWrite, "ffsdrv_null_write_end()" NL));
118 }
119
120 void ffsdrv_null_erase_end(void)
121 {
122 ttw(str(TTrDrvErase, "ffsdrv_null_erase_end()" NL));
123 }
124
125 /*
126 * FreeCalypso change from TI: we only compile one flash "driver" type
127 * based on the build configuration.
128 */
129
130 #if FFS_IN_RAM
131
132 /******************************************************************************
133 * RAM Family Functions
134 ******************************************************************************/
135
136 void ffsdrv_ram_write_halfword(volatile uint16 *dst, uint16 value)
137 {
138 *dst = value;
139 }
140
141 #if 0
142 /* duplicates ffsdrv_generic_write */
143 void ffsdrv_ram_write(void *dst, const void *src, uint16 size)
144 {
145 uint8 *mydst = dst;
146 const uint8 *mysrc = src;
147
148 if (size == 0)
149 return;
150 else if (size == 1)
151 ffsdrv_write_byte(mydst, *mysrc);
152 else {
153 if ((int) mydst & 1) {
154 ffsdrv_write_byte(mydst++, *mysrc++);
155 size--;
156 }
157 while (size >= 2) {
158 ffsdrv_ram_write_halfword((uint16 *) mydst, mysrc[0]|(mysrc[1] << 8));
159 size -= 2;
160 mysrc += 2;
161 mydst += 2;
162 }
163 if (size == 1)
164 ffsdrv_write_byte(mydst++, *mysrc++);
165 }
166 }
167 #endif
168
169 void ffsdrv_ram_erase(uint8 block)
170 {
171 int i;
172 char *addr;
173
174 addr = block2addr(block);
175
176 for (i = 0; i < (1 << dev.binfo[block].size_ld); i++) {
177 *addr++ = 0xFF;
178 }
179 }
180
181 const struct ffsdrv_s ffsdrv = {
182 ffsdrv_null_init,
183 ffsdrv_ram_erase,
184 ffsdrv_ram_write_halfword,
185 ffsdrv_generic_write,
186 ffsdrv_null_write_end,
187 ffsdrv_null_erase_suspend,
188 ffsdrv_null_erase_resume
189 };
190
191 #elif CONFIG_FLASH_WRITE
192
193 #if FLASH_IS_AMD_MULTIBANK
194
195 /******************************************************************************
196 * AMD Dual/Multi Bank Driver Functions
197 ******************************************************************************/
198
199 // All erase and write operations are performed atomically (interrupts
200 // disabled). Otherwise we cannot trust the value of dev.state and we cannot
201 // determine exactly how many of the command words have already been
202 // written.
203
204 // in ffs_end() when we resume an erasure that was previously suspended, how
205 // does that affect multiple tasks doing that simultaneously?
206
207 void ffsdrv_amd_write_end(void);
208 void ffsdrv_amd_erase_end(void);
209
210 void ffsdrv_amd_write_halfword(volatile uint16 *addr, uint16 value)
211 {
212 volatile uint16 *flash = (volatile uint16 *)dev.base;
213 uint32 cpsr;
214
215 tlw(led_on(LED_WRITE));
216 ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));
217
218 dev.addr = addr;
219 dev.data = value;
220
221 if (~*addr & value) {
222 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
223 return;
224 }
225
226 cpsr = int_disable();
227 tlw(led_toggle(LED_WRITE_SUSPEND));
228 dev.state = DEV_WRITE;
229 flash[0x555] = 0xAA; // unlock cycle 1
230 flash[0x2AA] = 0x55; // unlock cycle 2
231 flash[0x555] = 0xA0;
232 *addr = value;
233 int_enable(cpsr);
234 tlw(led_toggle(LED_WRITE_SUSPEND));
235
236 ffsdrv_amd_write_end();
237 }
238
239 #if 0
240 /* duplicates ffsdrv_generic_write */
241 void ffsdrv_amd_write(void *dst, const void *src, uint16 size)
242 {
243 uint8 *mydst = dst;
244 const uint8 *mysrc = src;
245
246 if (size > 0)
247 {
248 if ((unsigned int) mydst & 1) {
249 ffsdrv_write_byte(mydst++, *mysrc++);
250 size--;
251 }
252 while (size >= 2) {
253 ffsdrv_amd_write_halfword((uint16 *) mydst,
254 mysrc[0] | (mysrc[1] << 8));
255 size -= 2;
256 mysrc += 2;
257 mydst += 2;
258 }
259 if (size == 1)
260 ffsdrv_write_byte(mydst++, *mysrc++);
261 }
262 }
263 #endif
264
265 void ffsdrv_amd_write_end(void)
266 {
267 while ((*dev.addr ^ dev.data) & 0x80)
268 tlw(led_toggle(LED_WRITE_SUSPEND));
269
270 dev.state = DEV_READ;
271
272 tlw(led_off(LED_WRITE));
273 }
274
275 void ffsdrv_amd_erase(uint8 block)
276 {
277 volatile uint16 *flash = (volatile uint16 *)dev.base;
278 uint32 cpsr;
279
280 tlw(led_on(LED_ERASE));
281 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
282
283 dev.addr = (uint16 *) block2addr(block);
284
285 cpsr = int_disable();
286 dev.state = DEV_ERASE;
287 flash[0x555] = 0xAA; // unlock cycle 1
288 flash[0x2AA] = 0x55; // unlock cycle 2
289 flash[0x555] = 0x80;
290 flash[0x555] = 0xAA; // unlock cycle 1
291 flash[0x2AA] = 0x55; // unlock cycle 2
292 *dev.addr = 0x30; // AMD erase sector command
293 int_enable(cpsr);
294
295 ffsdrv_amd_erase_end();
296 }
297
298 void ffsdrv_amd_erase_end(void)
299 {
300 while ((*dev.addr & 0x80) == 0)
301 ;
302
303 dev.state = DEV_READ;
304
305 tlw(led_off(LED_ERASE));
306 }
307
308 void ffsdrv_amd_erase_suspend(void)
309 {
310 uint32 cpsr;
311
312 tlw(led_on(LED_ERASE_SUSPEND));
313 ttw(str(TTrDrvErase, "es" NL));
314
315 // if erase has finished then all is ok
316 if (*dev.addr & 0x80) {
317 ffsdrv_amd_erase_end();
318 tlw(led_off(LED_ERASE_SUSPEND));
319 return;
320 }
321
322 // NOTEME: As there is no way to be absolutely certain that erase
323 // doesn't finish between last poll and the following erase suspend
324 // command, we assume that the erase suspend is safe even though the
325 // erase IS actually already finished.
326
327 cpsr = int_disable();
328 dev.state = DEV_ERASE_SUSPEND;
329 *dev.addr = 0xB0;
330
331 // Wait for erase suspend to finish
332 while ((*dev.addr & 0x80) == 0)
333 ;
334
335 int_enable(cpsr);
336 }
337
338 void ffsdrv_amd_erase_resume(void)
339 {
340 uint32 cpsr;
341
342 ttw(str(TTrDrvErase, "er" NL));
343
344 // NOTEME: See note in erase_suspend()... We assume that the erase
345 // resume is safe even though the erase IS actually already finished.
346 cpsr = int_disable();
347 dev.state = DEV_ERASE;
348 *dev.addr = 0x30;
349 int_enable(cpsr);
350
351 tlw(led_off(LED_ERASE_SUSPEND));
352 }
353
354 const struct ffsdrv_s ffsdrv = {
355 ffsdrv_null_init,
356 ffsdrv_amd_erase,
357 ffsdrv_amd_write_halfword,
358 ffsdrv_generic_write,
359 ffsdrv_amd_write_end,
360 ffsdrv_amd_erase_suspend,
361 ffsdrv_amd_erase_resume
362 };
363
364 #elif FLASH_IS_INTEL_ONEBANK
365
366 extern int ffsdrv_ram_intel_sb_init(void);
367 extern void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr,
368 uint16 value);
369 extern void ffsdrv_ram_intel_sb_erase(uint8 block);
370
371 const struct ffsdrv_s ffsdrv = {
372 ffsdrv_ram_intel_sb_init,
373 ffsdrv_ram_intel_sb_erase,
374 ffsdrv_ram_intel_sb_write_halfword,
375 ffsdrv_generic_write,
376 ffsdrv_null_write_end,
377 ffsdrv_null_erase_suspend,
378 ffsdrv_null_erase_resume
379 };
380
381 #else
382
383 #error "Flash hardware type unknown"
384
385 #endif /* flash hardware type */
386
387 #else
388
389 /*
390 * This part will get compiled if we have real FFS (FFS_IN_RAM=0),
391 * but not allowed to write to flash (CONFIG_FLASH_WRITE=0).
392 */
393
394 const struct ffsdrv_s ffsdrv = {
395 ffsdrv_null_init,
396 ffsdrv_null_erase,
397 ffsdrv_null_write_halfword,
398 ffsdrv_null_write,
399 ffsdrv_null_write_end,
400 ffsdrv_null_erase_suspend,
401 ffsdrv_null_erase_resume
402 };
403
404 #endif
405
406
407 /******************************************************************************
408 * Initialization
409 *
410 * Significantly simplified in FreeCalypso.
411 *
412 ******************************************************************************/
413
414 effs_t ffsdrv_init(void)
415 {
416 int error;
417 unsigned i;
418 uint32 offset;
419
420 tw(tr(TR_BEGIN, TrDrvInit, "drv_init() {\n"));
421 ttw(str(TTrDrvOther, "ffsdrv_init() {" NL));
422
423 dev.state = DEV_READ;
424 dev.atomlog2 = FFS_ATOM_LOG2;
425 dev.atomsize = 1 << dev.atomlog2;
426 dev.atomnotmask = dev.atomsize - 1;
427
428 offset = 0;
429 for (i = 0; i < dev.numblocks; i++) {
430 block_info[i].offset = offset;
431 block_info[i].size_ld = dev.blocksize_ld;
432 offset += dev.blocksize;
433 }
434 dev.binfo = block_info;
435
436 error = ffsdrv.init();
437
438 tw(tr(TR_FUNC, TrDrvInit, "dev.binfo = 0x%x\n", (unsigned int) dev.binfo));
439 tw(tr(TR_FUNC, TrDrvInit, "dev.base = 0x%x\n", (unsigned int) dev.base));
440 tw(tr(TR_FUNC, TrDrvInit, "dev.numblocks = %d\n", dev.numblocks));
441 tw(tr(TR_FUNC, TrDrvInit, "dev.blocksize = %d\n", dev.blocksize));
442 tw(tr(TR_FUNC, TrDrvInit, "dev.atomlog2/atomsize/atomnotmask = %d/%d/%x\n",
443 dev.atomlog2, dev.atomsize, dev.atomnotmask));
444 tw(tr(TR_END, TrDrvInit, "} %d\n", error));
445 ttw(ttr(TTrDrvOther, "} %d" NL, error));
446
447 return error;
448 }