comparison src/cs/drivers/drv_app/ffs/board/amdsbdrv.c @ 0:b6a5e36de839

src/cs: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:39:26 +0000
parents
children 559a8b3ef10b
comparison
equal deleted inserted replaced
-1:000000000000 0:b6a5e36de839
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: amdsbdrv.c 1.5.1.3 Tue, 06 Jan 2004 10:57:45 +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 // Due to long branches, we disable all tracing and led function calls.
19 #undef tlw
20 #define tlw(contents)
21 #undef ttw
22 #define ttw(contents)
23
24
25 asm(" .label _ffsdrv_ram_amd_begin");
26 asm(" .def _ffsdrv_ram_amd_begin");
27
28
29 // IMPORTANT! Apparently, placing the int_disable/enable() function code
30 // here instead of at the bottom of the file, makes the code crash or
31 // freeze. Reason is as of yet unknown.
32
33 uint32 amd_int_disable(void);
34 void amd_int_enable(uint32 tmp);
35
36
37 /******************************************************************************
38 * AMD Single Bank Driver Functions
39 ******************************************************************************/
40
41 void ffsdrv_ram_amd_sb_write_halfword(volatile uint16 *addr, uint16 value)
42 {
43 volatile char *flash = dev.base;
44 uint32 cpsr;
45
46 ttw(ttr(TTrDrv, "wh(%x,%x)" NL, addr, value));
47
48 if (~*addr & value) {
49 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
50 return;
51 }
52
53 cpsr = amd_int_disable();
54 tlw(led_on(LED_WRITE));
55
56 flash[0xAAAA] = 0xAA; // AMD unlock cycle 1
57 flash[0x5555] = 0x55; // AMD unlock cycle 2
58 flash[0xAAAA] = 0xA0;
59 *addr = value;
60
61 while ((*addr ^ value) & 0x80)
62 ;
63
64 tlw(led_off(LED_WRITE));
65 amd_int_enable(cpsr);
66 }
67
68 // This VERY simple way of erase suspension only works because we run under
69 // a pre-emptive operating system, so whenever an interrupt occurs, another
70 // task takes the CPU, and at the end of the interrupt, FFS gets the CPU
71 // again.
72 void ffsdrv_ram_amd_sb_erase(uint8 block)
73 {
74 volatile char *flash = dev.base;
75 volatile char *addr;
76 uint32 cpsr;
77 uint16 flashpoll;
78
79 addr = block2addr(block);
80
81 ttw(ttr(TTrDrvEra, "e(%d)" NL, block));
82
83 cpsr = amd_int_disable();
84 tlw(led_on(LED_ERASE));
85
86 flash[0xAAAA] = 0xAA; // AMD unlock cycle 1
87 flash[0x5555] = 0x55; // AMD unlock cycle 2
88 flash[0xAAAA] = 0x80;
89 flash[0xAAAA] = 0xAA; // AMD unlock cycle 1
90 flash[0x5555] = 0x55; // AMD unlock cycle 2
91 *addr = 0x30; // AMD erase sector command
92
93 // Wait for erase to finish.
94 while ((*addr & 0x80) == 0) {
95 tlw(led_toggle(LED_ERASE));
96 // Poll interrupts, taking interrupt mask into account.
97 if (INT_REQUESTED)
98 {
99 // 1. suspend erase
100 // 2. enable interrupts
101 // .. now the interrupt code executes
102 // 3. disable interrupts
103 // 4. resume erase
104
105 tlw(led_on(LED_ERASE_SUSPEND));
106 *addr = 0xB0;
107
108 // wait for erase suspend to finish
109 while ((*addr & 0x80) == 0)
110 ;
111
112 tlw(led_off(LED_ERASE_SUSPEND));
113 amd_int_enable(cpsr);
114
115 // Other interrupts and tasks run now...
116
117 cpsr = amd_int_disable();
118 tlw(led_on(LED_ERASE_SUSPEND));
119
120 // Before resuming erase we must? check if the erase is really
121 // suspended or if it did finish
122 flashpoll = *addr;
123 *addr = 0x30;
124
125 tlw(led_off(LED_ERASE_SUSPEND));
126 }
127 }
128
129 tlw(led_on(LED_ERASE));
130 tlw(led_off(LED_ERASE));
131 amd_int_enable(cpsr);
132 }
133
134
135 /******************************************************************************
136 * Interrupt Enable/Disable
137 ******************************************************************************/
138
139 uint32 amd_int_disable(void)
140 {
141 asm(" .state16");
142 asm(" mov A1, #0xC0");
143 asm(" ldr A2, tct_amd_disable");
144 asm(" bx A2 ");
145
146 asm("tct_amd_disable .field _TCT_Control_Interrupts+0,32");
147 asm(" .global _TCT_Control_Interrupts");
148 }
149
150 void amd_int_enable(uint32 cpsr)
151 {
152 asm(" .state16");
153 asm(" ldr A2, tct_amd_enable");
154 asm(" bx A2 ");
155
156 asm("tct_amd_enable .field _TCT_Control_Interrupts+0,32");
157 asm(" .global _TCT_Control_Interrupts");
158 }
159
160 // Even though we have this end label, we cannot determine the number of
161 // constant/PC-relative data following the code!
162 asm(" .state32");
163 asm(" .label _ffsdrv_ram_amd_end");
164 asm(" .def _ffsdrv_ram_amd_end");