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