FreeCalypso > hg > fc-tourmaline
comparison src/cs/drivers/drv_app/ffs/board/amdsbdrv.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: 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 #ifdef __GNUC__ | |
26 asm(".globl ffsdrv_ram_amd_begin"); | |
27 asm("ffsdrv_ram_amd_begin:"); | |
28 #else | |
29 asm(" .label _ffsdrv_ram_amd_begin"); | |
30 asm(" .def _ffsdrv_ram_amd_begin"); | |
31 #endif | |
32 | |
33 | |
34 // IMPORTANT! Apparently, placing the int_disable/enable() function code | |
35 // here instead of at the bottom of the file, makes the code crash or | |
36 // freeze. Reason is as of yet unknown. | |
37 | |
38 uint32 amd_int_disable(void); | |
39 void amd_int_enable(uint32 tmp); | |
40 | |
41 | |
42 /****************************************************************************** | |
43 * AMD Single Bank Driver Functions | |
44 ******************************************************************************/ | |
45 | |
46 void ffsdrv_ram_amd_sb_write_halfword(volatile uint16 *addr, uint16 value) | |
47 { | |
48 volatile char *flash = dev.base; | |
49 uint32 cpsr; | |
50 | |
51 ttw(ttr(TTrDrv, "wh(%x,%x)" NL, addr, value)); | |
52 | |
53 if (~*addr & value) { | |
54 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value)); | |
55 return; | |
56 } | |
57 | |
58 cpsr = amd_int_disable(); | |
59 tlw(led_on(LED_WRITE)); | |
60 | |
61 flash[0xAAAA] = 0xAA; // AMD unlock cycle 1 | |
62 flash[0x5555] = 0x55; // AMD unlock cycle 2 | |
63 flash[0xAAAA] = 0xA0; | |
64 *addr = value; | |
65 | |
66 while ((*addr ^ value) & 0x80) | |
67 ; | |
68 | |
69 tlw(led_off(LED_WRITE)); | |
70 amd_int_enable(cpsr); | |
71 } | |
72 | |
73 // This VERY simple way of erase suspension only works because we run under | |
74 // a pre-emptive operating system, so whenever an interrupt occurs, another | |
75 // task takes the CPU, and at the end of the interrupt, FFS gets the CPU | |
76 // again. | |
77 void ffsdrv_ram_amd_sb_erase(uint8 block) | |
78 { | |
79 volatile char *flash = dev.base; | |
80 volatile char *addr; | |
81 uint32 cpsr; | |
82 uint16 flashpoll; | |
83 | |
84 addr = block2addr(block); | |
85 | |
86 ttw(ttr(TTrDrvEra, "e(%d)" NL, block)); | |
87 | |
88 cpsr = amd_int_disable(); | |
89 tlw(led_on(LED_ERASE)); | |
90 | |
91 flash[0xAAAA] = 0xAA; // AMD unlock cycle 1 | |
92 flash[0x5555] = 0x55; // AMD unlock cycle 2 | |
93 flash[0xAAAA] = 0x80; | |
94 flash[0xAAAA] = 0xAA; // AMD unlock cycle 1 | |
95 flash[0x5555] = 0x55; // AMD unlock cycle 2 | |
96 *addr = 0x30; // AMD erase sector command | |
97 | |
98 // Wait for erase to finish. | |
99 while ((*addr & 0x80) == 0) { | |
100 tlw(led_toggle(LED_ERASE)); | |
101 // Poll interrupts, taking interrupt mask into account. | |
102 if (INT_REQUESTED) | |
103 { | |
104 // 1. suspend erase | |
105 // 2. enable interrupts | |
106 // .. now the interrupt code executes | |
107 // 3. disable interrupts | |
108 // 4. resume erase | |
109 | |
110 tlw(led_on(LED_ERASE_SUSPEND)); | |
111 *addr = 0xB0; | |
112 | |
113 // wait for erase suspend to finish | |
114 while ((*addr & 0x80) == 0) | |
115 ; | |
116 | |
117 tlw(led_off(LED_ERASE_SUSPEND)); | |
118 amd_int_enable(cpsr); | |
119 | |
120 // Other interrupts and tasks run now... | |
121 | |
122 cpsr = amd_int_disable(); | |
123 tlw(led_on(LED_ERASE_SUSPEND)); | |
124 | |
125 // Before resuming erase we must? check if the erase is really | |
126 // suspended or if it did finish | |
127 flashpoll = *addr; | |
128 *addr = 0x30; | |
129 | |
130 tlw(led_off(LED_ERASE_SUSPEND)); | |
131 } | |
132 } | |
133 | |
134 tlw(led_on(LED_ERASE)); | |
135 tlw(led_off(LED_ERASE)); | |
136 amd_int_enable(cpsr); | |
137 } | |
138 | |
139 | |
140 /****************************************************************************** | |
141 * Interrupt Enable/Disable | |
142 ******************************************************************************/ | |
143 | |
144 #ifdef __GNUC__ | |
145 #define NOINLINE __attribute__ ((noinline)) | |
146 #else | |
147 #define NOINLINE | |
148 #endif | |
149 | |
150 uint32 NOINLINE amd_int_disable(void) | |
151 { | |
152 #ifdef __GNUC__ | |
153 asm(" .code 16"); | |
154 #else | |
155 asm(" .state16"); | |
156 #endif | |
157 asm(" mov A1, #0xC0"); | |
158 asm(" ldr A2, tct_amd_disable"); | |
159 asm(" bx A2 "); | |
160 | |
161 #ifdef __GNUC__ | |
162 asm(".balign 4"); | |
163 asm("tct_amd_disable:"); | |
164 asm(" .word TCT_Control_Interrupts"); | |
165 #else | |
166 asm("tct_amd_disable .field _TCT_Control_Interrupts+0,32"); | |
167 asm(" .global _TCT_Control_Interrupts"); | |
168 #endif | |
169 } | |
170 | |
171 void NOINLINE amd_int_enable(uint32 cpsr) | |
172 { | |
173 #ifdef __GNUC__ | |
174 asm(" .code 16"); | |
175 #else | |
176 asm(" .state16"); | |
177 #endif | |
178 asm(" ldr A2, tct_amd_enable"); | |
179 asm(" bx A2 "); | |
180 | |
181 #ifdef __GNUC__ | |
182 asm(".balign 4"); | |
183 asm("tct_amd_enable:"); | |
184 asm(" .word TCT_Control_Interrupts"); | |
185 #else | |
186 asm("tct_amd_enable .field _TCT_Control_Interrupts+0,32"); | |
187 asm(" .global _TCT_Control_Interrupts"); | |
188 #endif | |
189 } | |
190 | |
191 // Even though we have this end label, we cannot determine the number of | |
192 // constant/PC-relative data following the code! | |
193 #ifdef __GNUC__ | |
194 asm(".globl ffsdrv_ram_amd_end"); | |
195 asm("ffsdrv_ram_amd_end:"); | |
196 #else | |
197 asm(" .state32"); | |
198 asm(" .label _ffsdrv_ram_amd_end"); | |
199 asm(" .def _ffsdrv_ram_amd_end"); | |
200 #endif |