comparison gsm-fw/services/ffs/drv.c @ 209:6f4a12b4582f

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