comparison src/cs/drivers/drv_app/ffs/board/drv.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 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 #ifndef TARGET
12 #include "ffs.cfg"
13 #endif
14
15 #include "fc-target.h"
16
17 #include "ffs/ffs.h"
18 #include "ffs/board/drv.h"
19 #include "ffs/board/ffstrace.h"
20
21 #if (TARGET == 0)
22
23 #ifdef WIN32
24 #include "windows.h"
25 #else //WIN32
26 #include "sys/mman.h"
27 #include "unistd.h"
28 #endif //WIN32
29
30 #include "stdio.h"
31 #include "sys/types.h"
32 #include "sys/stat.h"
33 #include "fcntl.h"
34 #else
35 #include "nucleus.h"
36
37 #endif
38
39
40 // Note that all code notes and comments pertaining to single-bank flash
41 // drivers are located in the AMD SB driver (amdsbdrv.c). Consider this as
42 // the reference.
43
44
45 /******************************************************************************
46 * Globals
47 ******************************************************************************/
48
49 #if (TARGET == 1)
50 // NOTE: This is the size in bytes of the single-bank driver code that is
51 // copied to RAM. The only way to determine the amount of memory needed is
52 // to look into the linker output file (.map) or the assembler output of
53 // both amdsbdrv.obj and intelsbdrv.obj files.
54 #define FFSDRV_CODE_SIZE (0x200)
55
56 uint8 ffsdrv_code[FFSDRV_CODE_SIZE];
57
58 #endif
59
60 #define INTEL_UNLOCK_SLOW 1
61
62 struct dev_s dev;
63 struct ffsdrv_s ffsdrv;
64
65 uint32 int_disable(void);
66 void int_enable(uint32 tmp);
67
68 /******************************************************************************
69 * Macros
70 ******************************************************************************/
71
72 #define addr2offset(address) ( (int) (address) - (int) dev.base )
73
74
75 /******************************************************************************
76 * Generic Driver Functions
77 ******************************************************************************/
78
79 void ffsdrv_generic_write(void *dst, const void *src, uint16 size)
80 {
81 uint8 *mydst = dst;
82 const uint8 *mysrc = src;
83
84 if (size > 0)
85 {
86 if ((unsigned int) mydst & 1) {
87 ffsdrv_write_byte(mydst++, *mysrc++);
88 size--;
89 }
90 while (size >= 2) {
91 ffsdrv.write_halfword((uint16 *) mydst,
92 mysrc[0] | (mysrc[1] << 8));
93 size -= 2;
94 mysrc += 2;
95 mydst += 2;
96 }
97 if (size == 1)
98 ffsdrv_write_byte(mydst++, *mysrc++);
99 }
100 }
101
102
103 /******************************************************************************
104 * AMD Single Bank Driver Functions
105 ******************************************************************************/
106
107 #if (TARGET == 1)
108
109 // Forward declaration of functions in file amdsbdrv.c
110 void ffsdrv_ram_amd_sb_write_halfword(volatile uint16 *addr, uint16 value);
111 void ffsdrv_ram_amd_sb_erase(uint8 block);
112
113 #else // (TARGET == 0)
114
115 // On PC these functions are empty
116 void ffsdrv_ram_amd_sb_write_halfword(volatile uint16 *addr, uint16 value) {}
117 void ffsdrv_ram_amd_sb_erase(uint8 block) {}
118
119 #endif // (TARGET == 1)
120
121
122 /******************************************************************************
123 * AMD Pseudo Single Bank Driver Functions
124 ******************************************************************************/
125
126 // This is a pseudo single-bank flash driver. It simulates a single-bank
127 // flash device on a dual-bank device.
128
129 #if (TARGET == 1)
130
131 void ffsdrv_amd_pseudo_sb_write_halfword(volatile uint16 *addr, uint16 value)
132 {
133 volatile char *flash = dev.base;
134 uint32 cpsr, i, x;
135
136 ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));
137
138 if (~*addr & value) {
139 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
140 return;
141 }
142
143 cpsr = int_disable();
144 tlw(led_on(LED_WRITE));
145
146 flash[0xAAAA] = 0xAA; // unlock cycle 1
147 flash[0x5555] = 0x55; // unlock cycle 2
148 flash[0xAAAA] = 0xA0;
149 *addr = value;
150
151 while ((*dev.addr ^ dev.data) & 0x80)
152 ;
153
154 tlw(led_off(LED_WRITE));
155 int_enable(cpsr);
156 }
157
158 // This VERY simple way of erase suspending only works because we run under
159 // a pre-emptive operating system, so whenever an interrupt occurs, another
160 // task takes the CPU, and at the end of the interrupt, FFS gets the CPU
161 // again.
162 void ffsdrv_amd_pseudo_sb_erase(uint8 block)
163 {
164 volatile char *flash = dev.base;
165 volatile char *addr;
166 uint32 cpsr;
167 uint16 flashpoll;
168
169 addr = block2addr(block);
170
171 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
172
173 cpsr = int_disable();
174 tlw(led_on(LED_ERASE));
175
176 flash[0xAAAA] = 0xAA; // unlock cycle 1
177 flash[0x5555] = 0x55; // unlock cycle 2
178 flash[0xAAAA] = 0x80;
179 flash[0xAAAA] = 0xAA; // unlock cycle 1
180 flash[0x5555] = 0x55; // unlock cycle 2
181 *addr = 0x30; // AMD erase sector command
182
183 // Wait for erase to finish.
184 while ((*addr & 0x80) == 0) {
185 tlw(led_toggle(LED_ERASE));
186 // Poll interrupts, taking interrupt mask into account.
187 if (INT_REQUESTED)
188 {
189 // 1. suspend erase
190 // 2. enable interrupts
191 // .. now the interrupt code executes
192 // 3. disable interrupts
193 // 4. resume erase
194
195 tlw(led_on(LED_ERASE_SUSPEND));
196 *addr = 0xB0;
197
198 // wait for erase suspend to finish
199 while ((*addr & 0x80) == 0)
200 ;
201
202 tlw(led_off(LED_ERASE_SUSPEND));
203 int_enable(cpsr);
204
205 // Other interrupts and tasks run now...
206
207 cpsr = int_disable();
208 tlw(led_on(LED_ERASE_SUSPEND));
209
210 // Before resuming erase we must? check if the erase is really
211 // suspended or if it did finish
212 flashpoll = *addr;
213 *addr = 0x30;
214
215 tlw(led_off(LED_ERASE_SUSPEND));
216 }
217 }
218
219 tlw(led_on(LED_ERASE));
220 tlw(led_off(LED_ERASE));
221 int_enable(cpsr);
222 }
223
224 #else // (TARGET == 0)
225
226 void ffsdrv_amd_pseudo_sb_write_halfword(volatile uint16 *addr, uint16 value) {}
227 void ffsdrv_amd_pseudo_sb_erase(uint8 block) {}
228
229 #endif // (TARGET == 1)
230
231
232 /******************************************************************************
233 * AMD Dual/Multi Bank Driver Functions
234 ******************************************************************************/
235
236 // All erase and write operations are performed atomically (interrupts
237 // disabled). Otherwise we cannot trust the value of dev.state and we cannot
238 // determine exactly how many of the command words have already been
239 // written.
240
241 // in ffs_end() when we resume an erasure that was previously suspended, how
242 // does that affect multiple tasks doing that simultaneously?
243
244 void ffsdrv_amd_write_end(void);
245 void ffsdrv_amd_erase_end(void);
246
247 void ffsdrv_amd_write_halfword(volatile uint16 *addr, uint16 value)
248 {
249 volatile uint16 *flash = (volatile uint16 *)dev.base;
250 uint32 cpsr;
251
252 tlw(led_on(LED_WRITE));
253 ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));
254
255 dev.addr = addr;
256 dev.data = value;
257
258 if (~*addr & value) {
259 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
260 return;
261 }
262
263 cpsr = int_disable();
264 tlw(led_toggle(LED_WRITE_SUSPEND));
265 dev.state = DEV_WRITE;
266 flash[0x555] = 0xAA; // unlock cycle 1
267 flash[0x2AA] = 0x55; // unlock cycle 2
268 flash[0x555] = 0xA0;
269 *addr = value;
270 int_enable(cpsr);
271 tlw(led_toggle(LED_WRITE_SUSPEND));
272
273 ffsdrv_amd_write_end();
274 }
275
276 void ffsdrv_amd_write(void *dst, const void *src, uint16 size)
277 {
278 uint8 *mydst = dst;
279 const uint8 *mysrc = src;
280
281 if (size > 0)
282 {
283 if ((unsigned int) mydst & 1) {
284 ffsdrv_write_byte(mydst++, *mysrc++);
285 size--;
286 }
287 while (size >= 2) {
288 ffsdrv_amd_write_halfword((uint16 *) mydst,
289 mysrc[0] | (mysrc[1] << 8));
290 size -= 2;
291 mysrc += 2;
292 mydst += 2;
293 }
294 if (size == 1)
295 ffsdrv_write_byte(mydst++, *mysrc++);
296 }
297 }
298
299 void ffsdrv_amd_write_end(void)
300 {
301 while ((*dev.addr ^ dev.data) & 0x80)
302 tlw(led_toggle(LED_WRITE_SUSPEND));
303
304 dev.state = DEV_READ;
305
306 tlw(led_off(LED_WRITE));
307 }
308
309 void ffsdrv_amd_erase(uint8 block)
310 {
311 volatile uint16 *flash = (volatile uint16 *)dev.base;
312 uint32 cpsr;
313
314 tlw(led_on(LED_ERASE));
315 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
316
317 dev.addr = (uint16 *) block2addr(block);
318
319 cpsr = int_disable();
320 dev.state = DEV_ERASE;
321 flash[0x555] = 0xAA; // unlock cycle 1
322 flash[0x2AA] = 0x55; // unlock cycle 2
323 flash[0x555] = 0x80;
324 flash[0x555] = 0xAA; // unlock cycle 1
325 flash[0x2AA] = 0x55; // unlock cycle 2
326 *dev.addr = 0x30; // AMD erase sector command
327 int_enable(cpsr);
328
329 ffsdrv_amd_erase_end();
330 }
331
332 void ffsdrv_amd_erase_end(void)
333 {
334 while ((*dev.addr & 0x80) == 0)
335 ;
336
337 dev.state = DEV_READ;
338
339 tlw(led_off(LED_ERASE));
340 }
341
342 void ffsdrv_amd_erase_suspend(void)
343 {
344 uint32 cpsr;
345
346 tlw(led_on(LED_ERASE_SUSPEND));
347 ttw(str(TTrDrvErase, "es" NL));
348
349 // if erase has finished then all is ok
350 if (*dev.addr & 0x80) {
351 ffsdrv_amd_erase_end();
352 tlw(led_off(LED_ERASE_SUSPEND));
353 return;
354 }
355
356 // NOTEME: As there is no way to be absolutely certain that erase
357 // doesn't finish between last poll and the following erase suspend
358 // command, we assume that the erase suspend is safe even though the
359 // erase IS actually already finished.
360
361 cpsr = int_disable();
362 dev.state = DEV_ERASE_SUSPEND;
363 *dev.addr = 0xB0;
364
365 // Wait for erase suspend to finish
366 while ((*dev.addr & 0x80) == 0)
367 ;
368
369 int_enable(cpsr);
370 }
371
372 void ffsdrv_amd_erase_resume(void)
373 {
374 uint32 cpsr;
375
376 ttw(str(TTrDrvErase, "er" NL));
377
378 // NOTEME: See note in erase_suspend()... We assume that the erase
379 // resume is safe even though the erase IS actually already finished.
380 cpsr = int_disable();
381 dev.state = DEV_ERASE;
382 *dev.addr = 0x30;
383 int_enable(cpsr);
384
385 tlw(led_off(LED_ERASE_SUSPEND));
386 }
387
388
389 /******************************************************************************
390 * SST Dual/Multi Bank Driver Functions
391 ******************************************************************************/
392
393 // SST flashes use almost same command set as AMD flashes. Only the command
394 // addresses (4 more bits) and erase command data (0x50 instead of 0x30) are
395 // different. SST flashes have no erase suspend/resume commands because they
396 // are so fast at erasing!
397
398 void ffsdrv_sst_write_end(void);
399 void ffsdrv_sst_erase_end(void);
400
401 void ffsdrv_sst_write(void *dst, const void *src, uint16 size)
402 {
403 uint8 *mydst = dst;
404 const uint8 *mysrc = src;
405
406 if (size > 0)
407 {
408 if ((unsigned int) mydst & 1) {
409 ffsdrv_write_byte(mydst++, *mysrc++);
410 size--;
411 }
412 while (size >= 2) {
413 ffsdrv_amd_write_halfword((uint16 *) mydst,
414 mysrc[0] | (mysrc[1] << 8));
415 size -= 2;
416 mysrc += 2;
417 mydst += 2;
418 }
419 if (size == 1)
420 ffsdrv_write_byte(mydst++, *mysrc++);
421 }
422 }
423
424 // Note that SST flashes have smaller sectors than other flash families.
425 // Fortunately they support erasure of several of these sectors in a logical
426 // unit called a "block".
427 void ffsdrv_sst_erase(uint8 block)
428 {
429 volatile char *flash = dev.base;
430 uint32 cpsr;
431
432 tlw(led_on(LED_ERASE));
433 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
434
435 dev.addr = (uint16 *) block2addr(block);
436
437 cpsr = int_disable();
438 dev.state = DEV_ERASE;
439 flash[0xAAAA] = 0xAA; // unlock cycle 1
440 flash[0x5555] = 0x55; // unlock cycle 2
441 flash[0xAAAA] = 0x80;
442 flash[0xAAAA] = 0xAA; // unlock cycle 1
443 flash[0x5555] = 0x55; // unlock cycle 2
444 *dev.addr = 0x50; // SST erase block command
445 int_enable(cpsr);
446
447 ffsdrv_sst_erase_end();
448 }
449
450 void ffsdrv_sst_erase_end(void)
451 {
452 // Wait for erase end
453 while ((*dev.addr & 0x80) == 0)
454 ;
455
456 dev.state = DEV_READ;
457
458 tlw(led_off(LED_ERASE));
459 }
460
461 // Erase suspend/resume commands do not exist for SST flashes, so we just
462 // poll for the end of the erase operation...
463
464 void ffsdrv_sst_erase_suspend(void)
465 {
466 ttw(str(TTrDrvErase, "es" NL));
467
468 ffsdrv_sst_erase_end();
469 }
470
471
472 /******************************************************************************
473 * Intel Single Bank Driver Functions
474 ******************************************************************************/
475
476 #if (TARGET == 1)
477
478 // Forward declaration of functions in file intelsbdrv.c
479 int ffsdrv_ram_intel_sb_init(void);
480 void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value);
481 void ffsdrv_ram_intel_sb_erase(uint8 block);
482 void ffsdrv_ram_intel_erase(uint8 block);
483
484 #else // (TARGET == 0)
485
486 // On PC these functions are empty
487 void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value) {}
488 void ffsdrv_ram_intel_sb_erase(uint8 block) {}
489 void ffsdrv_ram_intel_erase(uint8 block) {}
490
491 #endif // (TARGET == 1)
492
493
494 /******************************************************************************
495 * Intel Dual/Multi Bank Driver Functions
496 ******************************************************************************/
497
498 void ffsdrv_intel_write_end(void);
499 void ffsdrv_intel_erase_end(void);
500
501
502 // ffsdrv_intel_write_halfword and ffsdrv_intel_write_end is not used
503 // because of the bug in the intel flash device. Instead is the functions
504 // ffsdrv_ram_intel_sb_write_halfword and ffsdrv_ram_intel_erase used.
505 void ffsdrv_intel_write_halfword(volatile uint16 *addr, uint16 value)
506 {
507 uint32 cpsr;
508
509 tlw(led_on(LED_WRITE));
510 ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));
511
512 dev.addr = addr;
513
514 if (~*addr & value) {
515 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
516 return;
517 }
518
519 cpsr = int_disable();
520 dev.state = DEV_WRITE;
521
522 #if (INTEL_UNLOCK_SLOW == 1)
523 *addr = 0x60; // Intel Config setup
524 *addr = 0xD0; // Intel Unlock block
525 *addr = 0x50; // Intel Clear Status Register
526 #endif
527
528 *addr = 0x40; // Intel program byte/word
529 *addr = value;
530
531 int_enable(cpsr);
532
533 ffsdrv_intel_write_end();
534 }
535
536 void ffsdrv_intel_write(void *dst, const void *src, uint16 size)
537 {
538 uint8 *mydst = dst;
539 const uint8 *mysrc = src;
540
541 if (size > 0)
542 {
543 if ((unsigned int) mydst & 1) {
544 ffsdrv_write_byte(mydst++, *mysrc++);
545 size--;
546 }
547 while (size >= 2) {
548 ffsdrv_intel_write_halfword((uint16 *) mydst,
549 mysrc[0] | (mysrc[1] << 8));
550 size -= 2;
551 mysrc += 2;
552 mydst += 2;
553 }
554 if (size == 1)
555 ffsdrv_write_byte(mydst++, *mysrc++);
556 }
557 }
558
559 void ffsdrv_intel_write_end(void)
560 {
561 uint32 cpsr;
562 // We can be interrupted and reentered thus the state can have been changed.
563 while ((*dev.addr & 0x80) == 0 && dev.state == DEV_WRITE)
564 ;
565
566 // The flash state and dev.state must be in sync thus the stat changes
567 // must be protect from being interrupted
568 cpsr = int_disable();
569 *dev.addr = 0xFF; // Intel read array
570 dev.state = DEV_READ;
571 int_enable(cpsr);
572
573 tlw(led_off(LED_WRITE));
574 }
575
576
577 void ffsdrv_intel_erase(uint8 block)
578 {
579 uint32 cpsr;
580
581 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
582 tlw(led_on(LED_ERASE));
583
584 dev.addr = (uint16 *) block2addr(block);
585
586 cpsr = int_disable();
587 dev.state = DEV_ERASE;
588
589 #if (INTEL_UNLOCK_SLOW == 1)
590 *dev.addr = 0x60; // Intel Config setup
591 *dev.addr = 0xD0; // Intel Unlock block
592 #endif
593
594 *dev.addr = 0x50; // Intel clear status register (not really necessary)
595 *dev.addr = 0x20; // Intel erase setup
596 *dev.addr = 0xD0; // Intel erase confirm
597
598 int_enable(cpsr);
599
600 ffsdrv_intel_erase_end();
601 }
602
603 void ffsdrv_intel_erase_end(void)
604 {
605 while ((*dev.addr & 0x80) == 0 && dev.state == DEV_ERASE)
606 ;
607
608 *dev.addr = 0xFF; // Intel read array
609
610 dev.state = DEV_READ;
611 tlw(led_off(LED_ERASE));
612 }
613
614 void ffsdrv_intel_erase_suspend(void)
615 {
616 uint32 cpsr;
617 uint16 poll;
618
619 ttw(str(TTrDrvErase, "es" NL));
620 tlw(led_on(LED_ERASE_SUSPEND));
621
622 cpsr = int_disable();
623 dev.state = DEV_ERASE_SUSPEND;
624 *dev.addr = 0xB0; // Intel Erase Suspend
625 *dev.addr = 0x70; // Intel Read Status Register
626 while (((poll = *dev.addr) & 0x80) == 0)
627 ;
628
629 if ((poll & 0x40) == 0) {
630 // Block erase has completed
631 tlw(led_off(LED_ERASE_SUSPEND));
632 dev.state = DEV_READ;
633 tlw(led_off(LED_ERASE));
634 }
635 *dev.addr = 0xFF; // Intel read array
636 int_enable(cpsr);
637 }
638
639 void ffsdrv_intel_erase_resume(void)
640 {
641 uint32 cpsr;
642
643 ttw(str(TTrDrvErase, "er" NL));
644
645 cpsr = int_disable();
646 dev.state = DEV_ERASE;
647 *dev.addr = 0xD0; // Intel erase resume
648
649 // The following "extra" Read Status command is required because Intel
650 // has changed the specification of the W30 flash! (See "1.8 Volt Intel®
651 // Wireless Flash Memory with 3 Volt I/O 28F6408W30, 28F640W30,
652 // 28F320W30 Specification Update")
653 *dev.addr = 0x70; // Intel Read Status Register
654
655 int_enable(cpsr);
656
657 tlw(led_off(LED_ERASE_SUSPEND));
658 }
659
660
661 /******************************************************************************
662 * RAM Family Functions
663 ******************************************************************************/
664
665 void ffsdrv_ram_write_halfword(volatile uint16 *dst, uint16 value)
666 {
667 *dst = value;
668 }
669
670 void ffsdrv_ram_write(void *dst, const void *src, uint16 size)
671 {
672 uint8 *mydst = dst;
673 const uint8 *mysrc = src;
674
675 if (size == 0)
676 return;
677 else if (size == 1)
678 ffsdrv_write_byte(mydst, *mysrc);
679 else {
680 if ((int) mydst & 1) {
681 ffsdrv_write_byte(mydst++, *mysrc++);
682 size--;
683 }
684 while (size >= 2) {
685 ffsdrv_ram_write_halfword((uint16 *) mydst, mysrc[0]|(mysrc[1] << 8));
686 size -= 2;
687 mysrc += 2;
688 mydst += 2;
689 }
690 if (size == 1)
691 ffsdrv_write_byte(mydst++, *mysrc++);
692 }
693 }
694
695 void ffsdrv_ram_erase(uint8 block)
696 {
697 int i;
698 char *addr;
699
700 addr = block2addr(block);
701
702 for (i = 0; i < (1 << dev.binfo[block].size_ld); i++) {
703 *addr++ = 0xFF;
704 }
705 }
706
707 /******************************************************************************
708 * Void Functions
709 ******************************************************************************/
710
711 int ffsdrv_null_init(void)
712 {
713 ttw(ttr(TTrDrvOther, "ffsdrv_null_init()" NL));
714
715 return 0;
716 }
717
718 void ffsdrv_null_erase(uint8 block)
719 {
720 ttw(ttr(TTrDrvErase, "ffsdrv_null_erase(%d)" NL, block));
721 }
722
723 void ffsdrv_null_write_halfword(volatile uint16 *addr, uint16 value)
724 {
725 ttw(ttr(TTrDrvWrite, "ffsdrv_null_write_halfword(0x%x, 0x%x)" NL, addr, value));
726 }
727
728 void ffsdrv_null_write(void *dst, const void *src, uint16 size)
729 {
730 ttw(ttr(TTrDrvWrite, "ffsdrv_null_write(0x%x, 0x%x, %d)" NL, dst, src, size));
731 }
732
733 void ffsdrv_null_erase_suspend(void)
734 {
735 ttw(str(TTrDrvErase, "ffsdrv_null_erase_suspend()" NL));
736 }
737
738 void ffsdrv_null_erase_resume(void)
739 {
740 ttw(str(TTrDrvErase, "ffsdrv_null_erase_resume()" NL));
741 }
742
743 void ffsdrv_null_write_end(void)
744 {
745 ttw(str(TTrDrvWrite, "ffsdrv_null_write_end()" NL));
746 }
747
748 void ffsdrv_null_erase_end(void)
749 {
750 ttw(str(TTrDrvErase, "ffsdrv_null_erase_end()" NL));
751 }
752
753
754 /******************************************************************************
755 * Test Driver Functions
756 ******************************************************************************/
757
758 #if (TARGET == 0)
759
760 static char *image_addr = 0;
761 static int image_size = 0;
762 #ifdef WIN32
763 HANDLE image_fd, map_fd;
764 #else //WIN32
765 static int image_fd = 0;
766 #endif //WIN32
767
768 extern int arg_removeimage;
769 extern char *arg_imagename;
770
771 extern void test_fatal_printf(char *format, ...);
772
773 void ffsdrv_write_check(char *addr, int size)
774 {
775 offset_t offset, last;
776
777 offset = addr2offset(addr);
778 last = dev.binfo[dev.numblocks-1].offset
779 + (1 << dev.binfo[dev.numblocks-1].size_ld);
780
781 if (offset < 0 || (offset + size) > last) {
782 fprintf(stderr, "ffsdrv_write_check() failed (addr = 0x%x, size = %d)\n",
783 (int) addr, size);
784 fprintf(stdout, "ffsdrv_write_check() failed (addr = 0x%x, size = %d)\n",
785 (int) addr, size);
786 exit (1);
787 }
788 }
789
790
791 void ffsdrv_write_error(uint16 old, uint16 new)
792 {
793 test_fatal_printf("FATAL: Attempt to rewrite 0 to 1 bit "
794 "(old:0x%x/%c new:0x%x/%c)\n",
795 old, (old < ' ' ? '?' : old),
796 new, (new < ' ' ? '?' : new));
797 }
798
799 void ffsdrv_test_write_halfword(volatile uint16 *addr, uint16 value)
800 {
801 tw(tr(TR_FUNC, TrDrvWrite, "test_write_halfword(0x%05x, 0x%x)\n",
802 addr2offset(addr), value));
803
804 ffsdrv_write_check((uint8 *) addr, 2);
805
806 if (~*addr & value)
807 ffsdrv_write_error(*addr, value);
808
809 *addr = value;
810 }
811
812 void ffsdrv_test_write(void *dst, const void *src, uint16 size)
813 {
814 uint8 *mydst = dst;
815 const uint8 *mysrc = src;
816
817 tw(tr(TR_FUNC, TrDrvWrite, "test_write(0x%05x, 0x%x, %d)\n",
818 addr2offset(mydst), mysrc, size));
819
820 if (size > 0)
821 {
822 if ((int) mydst & 1) {
823 ffsdrv_write_byte(mydst++, *mysrc++);
824 size--;
825 }
826 while (size >= 2) {
827 ffsdrv_test_write_halfword((uint16 *) mydst, mysrc[0]|(mysrc[1] << 8));
828 size -= 2;
829 mysrc += 2;
830 mydst += 2;
831 }
832 if (size == 1)
833 ffsdrv_write_byte(mydst++, *mysrc++);
834 }
835 }
836
837 void ffsdrv_test_erase(uint8 block)
838 {
839 int i;
840 uint8 *addr;
841
842 addr = block2addr(block);
843
844 tw(tr(TR_FUNC, TrDrvErase, "ffsdrv_test_erase(%d)\n", block));
845
846 for (i = 0; i < 1 << dev.binfo[block].size_ld; i++) {
847 *addr++ = 0xFF;
848 }
849 }
850
851 char *ffsdrv_test_create(void)
852 {
853 // If flash image file already exists, open the file, and mmap it.
854 // Otherwise, create file, fill file with 1's, then mmap it.
855
856 int i;
857 struct stat statbuf;
858 #ifdef WIN32
859 OFSTRUCT lpReOpenBuff;
860 DWORD last_error;
861 SECURITY_ATTRIBUTES lpAttributes;
862
863 lpAttributes.nLength = sizeof (lpAttributes);
864 lpAttributes.lpSecurityDescriptor = NULL;
865 lpAttributes.bInheritHandle = TRUE;
866 #endif
867 image_size = (int) dev.binfo[dev.numblocks - 1].offset +
868 (1 << dev.binfo[dev.numblocks - 1].size_ld);
869
870 tw(tr(TR_BEGIN, TrDrvInit, "ffsdrv_test_create() {\n"));
871 tw(tr(TR_FUNC, TrDrvInit, "%s image: '%s', size = %d\n",
872 arg_removeimage ? "new" : "current", arg_imagename, image_size));
873
874 // create file if it does not exist
875 #ifdef WIN32
876 if( arg_removeimage || OpenFile( arg_imagename, &lpReOpenBuff, OF_EXIST) == HFILE_ERROR )
877 #else
878 if (arg_removeimage || lstat(arg_imagename, &statbuf) == -1)
879 #endif
880 {
881 char data[64];
882 #ifdef WIN32
883 DWORD bwritten;
884 #endif
885 // only the first run should remove the flash image file
886 arg_removeimage = 0;
887
888 tw(tr(TR_FUNC, TrDrvInit, "creating new flash image file '%s'\n",
889 arg_imagename));
890 #ifdef WIN32
891 image_fd = CreateFile(arg_imagename,
892 GENERIC_WRITE | GENERIC_READ,
893 0,
894 NULL,
895 OPEN_ALWAYS,
896 FILE_ATTRIBUTE_NORMAL,
897 NULL );
898 #else
899 image_fd = open(arg_imagename , O_RDWR|O_CREAT,
900 (S_IRWXU & ~S_IXUSR) |
901 ( S_IRWXG & ~S_IXGRP) | (S_IRWXO & ~S_IXOTH));
902 #endif
903 if (image_fd == -1) {
904 perror("Failed to create flash image");
905 exit(1);
906 }
907
908 // write 1's to the file.
909 for (i = 0; i < 64; i++)
910 data[i] = 0xff;
911
912 #ifdef WIN32
913 for (i = 0; i < image_size/64; i++)
914 WriteFile(image_fd, data, 64, &bwritten, NULL);
915 CloseHandle(image_fd);
916 #else
917 for (i = 0; i < image_size/64; i++)
918 write(image_fd, data, 64);
919
920 close(image_fd);
921 #endif
922 image_fd = 0;
923 tw(tr(TR_FUNC, TrDrvInit, "flash image file created\n"));
924 }
925
926 // only open image file if this is the first initialization.
927 if (image_fd > 0) {
928 tw(tr(TR_FUNC, TrDrvInit, "re-opening '%s' file of size %d\n",
929 arg_imagename, image_size));
930 }
931 else {
932 tw(tr(TR_FUNC, TrDrvInit, "opening '%s' file of size %d\n",
933 arg_imagename, image_size));
934
935 #ifdef WIN32
936 image_fd = OpenFile( arg_imagename, &lpReOpenBuff, OF_READWRITE);
937 map_fd = CreateFileMapping (image_fd,
938 &lpAttributes,
939 PAGE_READWRITE,
940 0,
941 0,
942 arg_imagename);
943 #else
944 image_fd = open(arg_imagename, O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
945 #endif
946 if (image_fd == -1) {
947 perror("Failed to open flash image");
948 exit(1);
949 }
950
951 // memory map the file and update block addresses of binfo array
952 #ifdef WIN32
953 image_addr = MapViewOfFile( map_fd,
954 FILE_MAP_ALL_ACCESS,
955 0,
956 0,
957 0);
958 #else
959 image_addr = mmap(0, image_size, PROT_READ|PROT_WRITE,
960 MAP_FILE|MAP_SHARED, image_fd, 0);
961 #endif
962 }
963
964 tw(tr(TR_END, TrDrvInit, "}\n"));
965
966 return image_addr;
967 }
968
969 #endif // (TARGET == 0)
970
971
972 /******************************************************************************
973 * Device Detection and Copying of Driver to RAM
974 ******************************************************************************/
975
976 #if (TARGET == 1)
977
978 // Note that this function reads device code of any of the three known flash
979 // families; Intel, AMD and SST. This works because Intel and AMD use
980 // the same command data for entering READ_IDENTIFIER mode (0x90).
981 // The function should be copied and executed from RAM!
982 void ffsdrv_device_id_read(uint16 *manufact, uint16 *device)
983 {
984 #if defined(CONFIG_TARGET_FCFAM) || defined(CONFIG_TARGET_PIRELLI) || \
985 defined(__GNUC__)
986 /*
987 * This new FreeCalypso version of the device ID read function
988 * should work for all current targets, but we are being conservative
989 * and only enabling it for those targets for which it is required,
990 * i.e., where TI's original version does not work.
991 *
992 * Selenite change: for the gcc version we need to use this new
993 * autodetect code for all targets, TI's original version won't work
994 * because we run with the Calypso boot ROM at 0.
995 */
996
997 int addr, half, base, i;
998
999 /*
1000 * We operate at a non-zero erase block boundary so that this ID read
1001 * operation will still work in our newer FreeCalypso environments
1002 * where we have the Calypso boot ROM mapped at 0.
1003 */
1004 base = 0x40000;
1005
1006 /*
1007 * muckery similar to TI's original to avoid literal pool loads,
1008 * but we produce and use 0xAAA and 0x554 offsets instead of TI's
1009 * original 0xAAAA and 0x5555.
1010 */
1011 for (i = 0, addr = 0; i < 3; i++)
1012 addr = addr << 4 | 0xA;
1013 half = (addr >> 1) & ~1;
1014
1015 FLASH_WRITE_HALFWORD (base + addr, 0xAA);
1016 FLASH_WRITE_HALFWORD (base + half, 0x55);
1017 FLASH_WRITE_HALFWORD (base + addr, 0x90); // Intel/AMD read id command
1018
1019 *manufact = FLASH_READ_HALFWORD (base + 0); // flash a0 = 0
1020 *device = FLASH_READ_HALFWORD (base + 2); // flash a0 = 1
1021
1022 // Read extended id
1023 device[1] = FLASH_READ_HALFWORD (base + (0xE << 1));
1024 device[2] = FLASH_READ_HALFWORD (base + (0xF << 1));
1025 FLASH_WRITE_HALFWORD (base, 0xFF); // Intel read-array command
1026
1027 // AMD devices do not need the two unlock cycles but SST devices do,
1028 // even though the SST datasheets states otherwise ;-)
1029 FLASH_WRITE_HALFWORD (base + addr, 0xAA);
1030 FLASH_WRITE_HALFWORD (base + half, 0x55);
1031 FLASH_WRITE_HALFWORD (base + addr, 0xF0); // AMD read-array/reset command
1032 #else
1033 /* TI's original version */
1034 int addr, i;
1035
1036 // This silly looking code has one purpose; to set addr = 0xAAAA. It is
1037 // necessary in order to force the compiler NOT to produce code that
1038 // uses LDR opcode(s) with PC-relative addressing. The assember code
1039 // produced from this C code is completely relocatable!
1040 for (i = 0, addr = 0; i < 2; i++)
1041 addr |= addr << 8 | 0xAA;
1042
1043 FLASH_WRITE_HALFWORD (addr, 0xAA);
1044 FLASH_WRITE_HALFWORD (addr >> 1, 0x55);
1045 FLASH_WRITE_HALFWORD (addr, 0x90); // Intel/AMD read id command
1046
1047 *manufact = FLASH_READ_HALFWORD (0); // flash a0 = 0
1048 *device = FLASH_READ_HALFWORD (2); // flash a0 = 1
1049
1050 // Read extended id
1051 device[1] = FLASH_READ_HALFWORD (0xE << 1);
1052 device[2] = FLASH_READ_HALFWORD (0xF << 1);
1053 FLASH_WRITE_HALFWORD (0, 0xFF); // Intel read-array command
1054
1055 // AMD devices do not need the two unlock cycles but SST devices do,
1056 // even though the SST datasheets states otherwise ;-)
1057 FLASH_WRITE_HALFWORD (addr, 0xAA);
1058 FLASH_WRITE_HALFWORD (addr >> 1, 0x55);
1059 FLASH_WRITE_HALFWORD (addr, 0xF0); // AMD read-array/reset command
1060 #endif
1061 }
1062
1063 // Copy ffsdrv_device_id_read() function code to RAM. The only known way to
1064 // determine the size of the code is to look either in the linker-generated
1065 // map file or in the assember output file.
1066 void ffsdrv_device_id_read_copy_to_ram(uint16 *dst, int size)
1067 {
1068 uint16 *src = (uint16 *) &ffsdrv_device_id_read;
1069
1070 // The ARM7TDMI compiler sets bit 0 for thumb mode function pointers, so
1071 // we need to clear this in order to copy *all* bytes. Otherwise we
1072 // exclude first byte and the resulting copy becomes garbage
1073 src = (uint16 *) (~1 & (int) src);
1074 size /= 2;
1075
1076 while (size--)
1077 *dst++ = *src++;
1078 }
1079
1080 // Copy ffsdrv_xxx_sb_erase() and ffsdrv_xxx_sb_write_halfword() functions
1081 // to RAM. The only known way to determine the size of the code is to look
1082 // either in the linker-generated map file or in the assember output file.
1083 int ffsdrv_driver_copy_to_ram(int type)
1084 {
1085 int size;
1086 uint16 *src, *dst;
1087 extern uint16 ffsdrv_ram_amd_begin[];
1088 extern uint16 ffsdrv_ram_intel_begin[];
1089 uint32 offset_of_init;
1090 uint32 offset_of_erase;
1091 uint32 offset_of_write_halfword;
1092
1093 ttw(ttr(TTrDrvOther, "ffsdrv_driver_copy_to_ram() {" NL));
1094
1095 switch (type) {
1096 case FFS_DRIVER_AMD:
1097 case FFS_DRIVER_AMD_SB:
1098 src = ffsdrv_ram_amd_begin;
1099 offset_of_erase =
1100 (uint32) ffsdrv_ram_amd_sb_erase - (uint32) src;
1101 offset_of_write_halfword =
1102 (uint32) ffsdrv_ram_amd_sb_write_halfword - (uint32) src;
1103 break;
1104 case FFS_DRIVER_INTEL_SB:
1105 src = ffsdrv_ram_intel_begin;
1106 offset_of_init =
1107 (uint32) ffsdrv_ram_intel_sb_init - (uint32) src;
1108 offset_of_erase =
1109 (uint32) ffsdrv_ram_intel_sb_erase - (uint32) src;
1110 offset_of_write_halfword =
1111 (uint32) ffsdrv_ram_intel_sb_write_halfword - (uint32) src;
1112 break;
1113 case FFS_DRIVER_INTEL:
1114 src = ffsdrv_ram_intel_begin;
1115 offset_of_init =
1116 (uint32) ffsdrv_ram_intel_sb_init - (uint32) src;
1117 offset_of_erase =
1118 (uint32) ffsdrv_ram_intel_erase - (uint32) src;
1119 offset_of_write_halfword =
1120 (uint32) ffsdrv_ram_intel_sb_write_halfword - (uint32) src;
1121 break;
1122 default:
1123 ttw(ttr(TTrDrvOther, "}" NL));
1124 return 0;
1125 }
1126
1127 // Make sure we are handling a half-word aligned address (Thumb mode
1128 // function pointers have lsb set!)
1129 src = (uint16 *) (~1 & (int) src);
1130
1131 // If we detect that the linker allocated the driver to RUN in RAM, the
1132 // user has obviously NOT removed those linker lines and we bail out!
1133 if (offset_of_erase > FFSDRV_CODE_SIZE)
1134 return EFFS_DRIVER;
1135
1136 dst = (uint16 *) &ffsdrv_code;
1137
1138 // Code size in halfwords
1139 size = FFSDRV_CODE_SIZE / 2;
1140
1141 // Rebind the two changed driver functions
1142 if (type == FFS_DRIVER_AMD_SB || type == FFS_DRIVER_INTEL_SB) {
1143 ffsdrv.erase =
1144 (void (*)(uint8))
1145 (offset_of_erase + (uint32) dst);
1146 ffsdrv.write_halfword =
1147 (void (*)(volatile uint16 *, uint16))
1148 (offset_of_write_halfword + (uint32) dst);
1149 }
1150 if (type == FFS_DRIVER_INTEL_SB) {
1151 ffsdrv.init =
1152 (int (*)(void))
1153 (offset_of_init + (uint32) dst);
1154 }
1155
1156 ttw(ttr(TTrDrvOther, "ffsdrv_code, init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
1157 dst, (uint32) ffsdrv.init,
1158 (uint32) ffsdrv.write_halfword, (uint32) ffsdrv.erase));
1159
1160 ttw(ttr(TTrDrvOther, "amd_begin, init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
1161 ffsdrv_ram_amd_begin, ffsdrv_null_init,
1162 ffsdrv_ram_amd_sb_write_halfword, ffsdrv_ram_amd_sb_erase));
1163
1164 ttw(ttr(TTrDrvOther, "intel_begin, init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
1165 ffsdrv_ram_intel_begin, ffsdrv_ram_intel_sb_init,
1166 ffsdrv_ram_intel_sb_write_halfword, ffsdrv_ram_intel_sb_erase));
1167
1168 // Copy the code to RAM
1169 while (size--)
1170 *dst++ = *src++;
1171
1172 ttw(ttr(TTrDrvOther, "}" NL));
1173
1174 return 0;
1175 }
1176
1177 #if defined(CONFIG_TARGET_PIRELLI) || defined(CONFIG_TARGET_FCFAM)
1178
1179 #ifdef CONFIG_TARGET_FCFAM
1180 #define FLASH2_BASE_ADDR 0x01800000
1181 #elif defined(CONFIG_TARGET_PIRELLI)
1182 #define FLASH2_BASE_ADDR 0x02000000
1183 #endif
1184
1185 int ffsdrv_is_new_spansion_flash(void)
1186 {
1187 uint16 cfi_hi, cfi_lo, cfi_ver;
1188
1189 /* CFI query */
1190 FLASH_WRITE_HALFWORD(FLASH2_BASE_ADDR + 0xAAA, 0x98);
1191 cfi_hi = FLASH_READ_HALFWORD(FLASH2_BASE_ADDR + 0x86);
1192 cfi_lo = FLASH_READ_HALFWORD(FLASH2_BASE_ADDR + 0x88);
1193 cfi_ver = (cfi_hi << 8) | (cfi_lo & 0xFF);
1194
1195 /* return to read array mode */
1196 FLASH_WRITE_HALFWORD(FLASH2_BASE_ADDR + 0xAAA, 0xF0);
1197
1198 if (cfi_ver >= 0x3134)
1199 return 1;
1200 else
1201 return 0;
1202 }
1203 #endif
1204
1205 #else // (TARGET == 0)
1206
1207 void ffsdrv_device_id_read(uint16 *manufact, uint16 *device) {}
1208 int ffsdrv_driver_copy_to_ram(int type) { return 0; }
1209
1210 #endif // (TARGET == 1)
1211
1212
1213 /******************************************************************************
1214 * Initialization
1215 ******************************************************************************/
1216
1217 const struct ffsdrv_s ffsdrv_amd = {
1218 ffsdrv_null_init,
1219 ffsdrv_amd_erase,
1220 ffsdrv_amd_write_halfword,
1221 ffsdrv_amd_write,
1222 ffsdrv_amd_write_end,
1223 ffsdrv_amd_erase_suspend,
1224 ffsdrv_amd_erase_resume
1225 };
1226
1227 const struct ffsdrv_s ffsdrv_amd_sb = {
1228 ffsdrv_null_init,
1229 ffsdrv_ram_amd_sb_erase,
1230 ffsdrv_ram_amd_sb_write_halfword,
1231 ffsdrv_generic_write,
1232 ffsdrv_null_write_end,
1233 ffsdrv_null_erase_suspend,
1234 ffsdrv_null_erase_resume
1235 };
1236
1237 const struct ffsdrv_s ffsdrv_sst = {
1238 ffsdrv_null_init,
1239 ffsdrv_sst_erase,
1240 ffsdrv_amd_write_halfword, // Use AMD driver function
1241 ffsdrv_sst_write,
1242 ffsdrv_amd_write_end, // Use AMD driver function
1243 ffsdrv_sst_erase_suspend,
1244 ffsdrv_null_erase_resume
1245 };
1246
1247 const struct ffsdrv_s ffsdrv_sst_sb = {
1248 ffsdrv_null_init,
1249 ffsdrv_null_erase,
1250 ffsdrv_null_write_halfword,
1251 ffsdrv_null_write,
1252 ffsdrv_null_write_end,
1253 ffsdrv_null_erase_suspend,
1254 ffsdrv_null_erase_resume
1255 };
1256
1257 // We use the functions ffsdrv_ram_intel_sb_write_halfword and
1258 // ffsdrv_ram_intel_erase due to the bug in the intel wireless flash
1259 // device. See 28F640W30.pdf specification Errata 5.
1260 const struct ffsdrv_s ffsdrv_intel = {
1261 ffsdrv_null_init,
1262 ffsdrv_intel_erase,
1263 ffsdrv_intel_write_halfword,
1264 ffsdrv_generic_write,
1265 ffsdrv_intel_write_end,
1266 ffsdrv_intel_erase_suspend,
1267 ffsdrv_intel_erase_resume
1268 };
1269
1270 const struct ffsdrv_s ffsdrv_intel_sb = {
1271 ffsdrv_null_init,
1272 ffsdrv_ram_intel_sb_erase,
1273 ffsdrv_ram_intel_sb_write_halfword,
1274 ffsdrv_generic_write,
1275 ffsdrv_null_write_end,
1276 ffsdrv_null_erase_suspend,
1277 ffsdrv_null_erase_resume
1278 };
1279
1280 const struct ffsdrv_s ffsdrv_null = {
1281 ffsdrv_null_init,
1282 ffsdrv_null_erase,
1283 ffsdrv_null_write_halfword,
1284 ffsdrv_null_write,
1285 ffsdrv_null_write_end,
1286 ffsdrv_null_erase_suspend,
1287 ffsdrv_null_erase_resume
1288 };
1289
1290 const struct ffsdrv_s ffsdrv_amd_pseudo_sb = {
1291 ffsdrv_null_init,
1292 ffsdrv_amd_pseudo_sb_erase,
1293 ffsdrv_amd_pseudo_sb_write_halfword,
1294 ffsdrv_generic_write,
1295 ffsdrv_null_write_end,
1296 ffsdrv_null_erase_suspend,
1297 ffsdrv_null_erase_resume
1298 };
1299
1300 const struct ffsdrv_s ffsdrv_ram = {
1301 ffsdrv_null_init,
1302 ffsdrv_ram_erase,
1303 ffsdrv_ram_write_halfword,
1304 ffsdrv_ram_write,
1305 ffsdrv_null_write_end,
1306 ffsdrv_null_erase_suspend,
1307 ffsdrv_null_erase_resume
1308 };
1309
1310 #if (TARGET == 0)
1311 const struct ffsdrv_s ffsdrv_test = {
1312 ffsdrv_null_init,
1313 ffsdrv_test_erase,
1314 ffsdrv_test_write_halfword,
1315 ffsdrv_test_write,
1316 ffsdrv_null_write_end,
1317 ffsdrv_null_erase_suspend,
1318 ffsdrv_null_erase_resume
1319 };
1320 #endif
1321
1322 // Note: This function is designed for little-endian memory addressing!
1323 void ffsdrv_write_byte(void *dst, uint8 value)
1324 {
1325 uint16 halfword;
1326
1327 tw(tr(TR_FUNC, TrDrvWrite, "ffsdrv_write_byte(0x%05x, 0x%x)\n",
1328 (int) (addr2offset(dst)), value));
1329 ttw(str(TTrDrvWrite, "wb" NL));
1330
1331 if ((int) dst & 1)
1332 halfword = (value << 8) | *((uint8 *) dst - 1);
1333 else
1334 halfword = (*((uint8 *) dst + 1) << 8) | (value);
1335
1336 ffsdrv.write_halfword((uint16 *) ((int) dst & ~1), halfword);
1337 }
1338
1339
1340 extern uint16 ffs_flash_manufact;
1341 extern uint16 ffs_flash_device;
1342
1343 effs_t ffsdrv_init(void)
1344 {
1345 const struct ffsdrv_s *p;
1346 const struct flash_info_s *flash = &flash_info[0];
1347 int error;
1348
1349 tw(tr(TR_BEGIN, TrDrvInit, "drv_init() {\n"));
1350 ttw(str(TTrDrvOther, "ffsdrv_init() {" NL));
1351
1352 dev.state = DEV_READ;
1353 dev.binfo = 0;
1354 dev.base = 0;
1355 dev.numblocks = 0;
1356
1357 // If ffs_flash_device is zero, detect device automatically by copying
1358 // the detect function into RAM and execute it from there...
1359 if (ffs_flash_manufact == 0 && ffs_flash_device == 0)
1360 {
1361 #if (TARGET == 1)
1362 char detect_code[0x80];
1363 typedef (*pf_t)(uint16 *, uint16 *);
1364 pf_t myfp;
1365 uint16 device_id[3];
1366
1367 ffsdrv_device_id_read_copy_to_ram((uint16 *) detect_code,
1368 sizeof(detect_code));
1369 // Combine bit 0 of the thumb mode function pointer with the address
1370 // of the code in RAM. Then call the detect function in RAM.
1371 #ifdef __GNUC__
1372 /* gcc fails to do the needed trick, so force Thumb */
1373 myfp = (pf_t) (((int) detect_code) | 1);
1374 #else
1375 myfp = (pf_t) (((int) &ffsdrv_device_id_read & 1) | (int) detect_code);
1376 #endif
1377 (*myfp)(&dev.manufact, device_id);
1378
1379 if ((dev.manufact == MANUFACT_AMD || dev.manufact == MANUFACT_FUJITSU) &&
1380 device_id[0] == 0x227E) {
1381 // This is a multi-id device
1382 dev.device = (device_id[1] << 8) | (device_id[2] & 0xFF);
1383 #if defined(CONFIG_TARGET_PIRELLI) || defined(CONFIG_TARGET_FCFAM)
1384 if (device_id[1] == 0x2221 && device_id[2] == 0x2200)
1385 dev.device += ffsdrv_is_new_spansion_flash();
1386 #endif
1387 }
1388 else if (dev.manufact == MANUFACT_SAMSUNG && device_id[0] == 0x257E) {
1389 /* Samsung's version of extended ID */
1390 dev.device = (device_id[1] << 8) | (device_id[2] & 0xFF);
1391 }
1392 else
1393 dev.device = device_id[0];
1394 #endif
1395 }
1396 else {
1397 dev.manufact = ffs_flash_manufact;
1398 dev.device = ffs_flash_device;
1399 }
1400
1401 tw(tr(TR_FUNC, TrDrvInit, "TARGET = %d\n", TARGET));
1402 tw(tr(TR_FUNC, TrDrvInit, "Looking up device (0x%2x,0x%4x): ",
1403 dev.manufact, dev.device));
1404 while (flash->manufact) {
1405 tw(tr(TR_NULL, TrDrvInit, "(0x%02x,0x%04x) ",
1406 flash->manufact, flash->device));
1407 if (dev.manufact == flash->manufact && dev.device == flash->device) {
1408 tw(tr(TR_NULL, TrDrvInit, "FOUND "));
1409 break;
1410 }
1411 flash++;
1412 }
1413 tw(tr(TR_NULL, TrDrvInit, "\n"));
1414
1415 if (flash->manufact == 0) {
1416 tw(tr(TR_END, TrDrvInit, "} (%d)\n", EFFS_NODEVICE));
1417 return EFFS_NODEVICE;
1418 }
1419
1420 dev.binfo = (struct block_info_s *) flash->binfo;
1421
1422 if (flash->driver == FFS_DRIVER_RAM && flash->base == 0) {
1423 if (ffs_ram_image_address <= 0) {
1424 tw(tr(TR_END, TrDrvInit, "} (%d)\n", EFFS_DRIVER));
1425 return EFFS_DRIVER;
1426 }
1427 dev.base = (char *) ffs_ram_image_address;
1428 }
1429 else
1430 dev.base = (char *) flash->base;
1431
1432 dev.numblocks = flash->numblocks;
1433 dev.driver = flash->driver;
1434
1435 // We assume that ALL blocks are of equal size
1436 dev.blocksize_ld = dev.binfo[0].size_ld;
1437 dev.blocksize = (1 << dev.blocksize_ld);
1438
1439 dev.atomlog2 = FFS_ATOM_LOG2;
1440 dev.atomsize = 1 << dev.atomlog2;
1441 dev.atomnotmask = dev.atomsize - 1;
1442
1443 #if (TARGET == 0)
1444 if (dev.manufact == MANUFACT_TEST)
1445 dev.base = ffsdrv_test_create();
1446
1447 p = &ffsdrv_test;
1448
1449 #else // (TARGET == 1)
1450
1451 // Initialize hardware independent driver functions array
1452 switch (dev.driver) {
1453 case FFS_DRIVER_AMD: p = &ffsdrv_amd; break;
1454 case FFS_DRIVER_AMD_SB: p = &ffsdrv_amd_sb; break;
1455 case FFS_DRIVER_SST: p = &ffsdrv_sst; break;
1456 case FFS_DRIVER_SST_SB: p = &ffsdrv_sst_sb; break;
1457 case FFS_DRIVER_INTEL: p = &ffsdrv_intel; break;
1458 case FFS_DRIVER_INTEL_SB: p = &ffsdrv_intel_sb; break;
1459 case FFS_DRIVER_AMD_PSEUDO_SB: p = &ffsdrv_amd_pseudo_sb; break;
1460 case FFS_DRIVER_RAM: p = &ffsdrv_ram; break;
1461 default: p = &ffsdrv_null; break;
1462 }
1463
1464 #endif // (TARGET == 0)
1465
1466 // Bind the driver functions
1467 ffsdrv.init = p->init;
1468 ffsdrv.erase = p->erase;
1469 ffsdrv.write_halfword = p->write_halfword;
1470 ffsdrv.write = p->write;
1471 ffsdrv.write_end = p->write_end;
1472 ffsdrv.erase_suspend = p->erase_suspend;
1473 ffsdrv.erase_resume = p->erase_resume;
1474
1475 // Copy single bank driver code to RAM (and possibly re-bind some of the
1476 // driver functions)
1477 error = ffsdrv_driver_copy_to_ram(dev.driver);
1478
1479 if (error >= 0)
1480 error = ffsdrv.init();
1481
1482 tw(tr(TR_FUNC, TrDrvInit, "dev.binfo = 0x%x\n", (unsigned int) dev.binfo));
1483 tw(tr(TR_FUNC, TrDrvInit, "dev.base = 0x%x\n", (unsigned int) dev.base));
1484 tw(tr(TR_FUNC, TrDrvInit, "dev.numblocks = %d\n", dev.numblocks));
1485 tw(tr(TR_FUNC, TrDrvInit, "dev.blocksize = %d\n", dev.blocksize));
1486 tw(tr(TR_FUNC, TrDrvInit, "dev.atomlog2/atomsize/atomnotmask = %d/%d/%x\n",
1487 dev.atomlog2, dev.atomsize, dev.atomnotmask));
1488 tw(tr(TR_END, TrDrvInit, "} %d\n", error));
1489 ttw(ttr(TTrDrvOther, "} %d" NL, error));
1490
1491 return error;
1492 }
1493
1494
1495 /******************************************************************************
1496 * Interrupt Enable/Disable
1497 ******************************************************************************/
1498
1499 // IMPORTANT NOTE! Apparently, locating this ARM assembly code at the top of
1500 // this file will make the compiler trash the A1 register between the calls
1501 // of arm_int_disable and arm_int_enable() thus crashing the whole system.
1502 // If the code is placed AFTER the usage of the functions, the compiler
1503 // saves the A1 register. Strange but true.
1504
1505 // IMPORTANT NOTE! Apparently, another strange thing is that if the
1506 // functions are declared static, they don't work!
1507
1508 // Executing code from RAM is NOT trivial when we need to jump between ROM
1509 // (flash) and RAM memory. The ARM only supports 26-bit relative branch
1510 // offsets. This is the reason why we have a local copy of the
1511 // arm_int_disable/enable() functions in this file plus each of the
1512 // single-bank drivers.
1513
1514 #if (TARGET == 1)
1515 // Note that we use our own interrupt disable/enable function because
1516 // Nucleus allegedly should have a bug in its implementation for this.
1517
1518 #ifdef __GNUC__
1519 #define NOINLINE __attribute__ ((noinline))
1520 #else
1521 #define NOINLINE
1522 #endif
1523
1524 uint32 NOINLINE int_disable(void)
1525 {
1526 #ifdef __GNUC__
1527 asm(" .code 16");
1528 #else
1529 asm(" .state16");
1530 #endif
1531 asm(" mov A1, #0xC0");
1532 asm(" ldr A2, tct_disable");
1533 asm(" bx A2 ");
1534
1535 #ifdef __GNUC__
1536 asm(".balign 4");
1537 asm("tct_disable:");
1538 asm(" .word TCT_Control_Interrupts");
1539 #else
1540 asm("tct_disable .field _TCT_Control_Interrupts+0,32");
1541 asm(" .global _TCT_Control_Interrupts");
1542 #endif
1543 }
1544
1545 void NOINLINE int_enable(uint32 cpsr)
1546 {
1547 #ifdef __GNUC__
1548 asm(" .code 16");
1549 #else
1550 asm(" .state16");
1551 #endif
1552 asm(" ldr A2, tct_enable");
1553 asm(" bx A2 ");
1554
1555 #ifdef __GNUC__
1556 asm(".balign 4");
1557 asm("tct_enable:");
1558 asm(" .word TCT_Control_Interrupts");
1559 #else
1560 asm("tct_enable .field _TCT_Control_Interrupts+0,32");
1561 asm(" .global _TCT_Control_Interrupts");
1562 #endif
1563 }
1564
1565 #else
1566
1567 uint32 int_disable(void) { return 0; }
1568 void int_enable(uint32 tmp) {}
1569
1570 #endif // (TARGET == 1)
1571
1572