MEGAWOOT: it just works \o/
[pyfrprog.git] / pkernel / flash.c
1 /*****************************************************************************/
2 /* THIS SAMPLE CODE IS PROVIDED AS IS AND IS SUBJECT TO ALTERATIONS. FUJITSU */
3 /* MICROELECTRONICS ACCEPTS NO RESPONSIBILITY OR LIABILITY FOR ANY ERRORS OR */
4 /* ELIGIBILITY FOR ANY PURPOSES.                                             */
5 /*                 (C) Fujitsu Microelectronics Europe GmbH                  */
6 /*****************************************************************************/
7
8 #include "flash.h"
9 #include "mb91465k.h"
10
11 static unsigned int IFlag;
12
13 void FLASH_PrepareWriteHalfWordMode()
14 {
15         /*      Set FLASH Access Mode via BootROM Routine       */
16         /*      For details refer to the Hardware Manual or Data Sheet */
17 #pragma asm
18         ST              RP,@-R15
19         STM0    (R4,R5)
20         STM1    (R12)
21         LDI             #0x01,R4        ; Set FLASH to 16Bit read/write Mode
22         LDI             #0x04,R5        ; Go 4 times through delay loop (64MHz CLKB)
23         LDI             #0xBF60,R12
24         CALL    @R12
25         LDM1    (R12)
26         LDM0    (R4,R5)
27         LD              @R15+,RP
28 #pragma endasm
29         
30         /*      Set the FLASH Interface to Write Timing */
31         /*      For details refer to the Hardware Manual or Data Sheet */
32         /*      Setting shown here is for CLKB = 64MHz  */
33         FMWT_ATD = 1;
34         FMWT_WEXH = 0;
35         FMWT_WTC = 8;
36 }
37
38 void FLASH_PrepareReadMode()
39 {
40         /*      Set FLASH Access Mode via BootROM Routine       */
41         /*      For details refer to the Hardware Manual or Data Sheet */
42 #pragma asm
43         ST              RP,@-R15
44         STM0    (R4,R5)
45         STM1    (R12)
46         LDI             #0x00,R4        ; Set FLASH to 32Bit read/write Mode
47         LDI             #0x04,R5        ; Go 4 times through delay loop (64MHz CLKB)
48         LDI             #0xBF60,R12
49         CALL    @R12
50         LDM1    (R12)
51         LDM0    (R4,R5)
52         LD              @R15+,RP
53 #pragma endasm
54         
55         /*      Set the FLASH Interface to Read Timing  */
56         /*      For details refer to the Hardware Manual or Data Sheet */
57         /*      Setting shown here is for CLKB = 64MHz  */
58         FMWT_ATD = 1;
59         FMWT_EQ = 3;
60         FMWT_WTC = 4;
61 }               
62                 
63 unsigned char FLASH_ChipErase(void)
64 {
65         unsigned char flag = 0;
66
67         /*Disable Interrupts if necessary*/
68         IFlag = FLASH_SaveDisableInterruptFlag();
69
70         /*Set FLASH access mode to 16Bit Write Mode*/
71         FLASH_PrepareWriteHalfWordMode();
72
73         /*Start FLASH Sector Erase Sequence*/
74         *hseq_1 = 0x00AA;
75         *hseq_2 = 0x0055;
76         *hseq_1 = 0x0080;
77         *hseq_1 = 0x00AA;
78         *hseq_2 = 0x0055;
79         *hseq_1 = 0x0010;
80
81         /*Wait for the Auto Algorithm to finish*/
82         while( flag == 0 ) {
83                 /* Feed Hardware Watchdog */
84                 HWWD_CL = 0;
85
86                 if(*hseq_1 & DPOLL) {
87                         flag = 1;
88                 }
89                 if(*hseq_1 & TLOVER) {
90                         if(*hseq_1 & DPOLL) {
91                                 flag = 1;
92                         }
93                         else {
94                                 /*Reset FLASH (keep in mind 16Bit access to FLASH)*/
95                                 *hseq_1 = 0x00F0; // Keep in Mind (16Bit access)
96
97                                 flag = 2;
98                         }
99                 }
100         }
101
102         /*Set FLASH access mode to 32Bit Read Mode*/
103         FLASH_PrepareReadMode();
104
105         /*Restore the original Interrupt Flag*/
106         FLASH_RestoreInterruptFlag(IFlag);
107
108         return flag;
109 }
110         
111 unsigned char FLASH_SectorErase(unsigned int secadr)
112 {
113         unsigned char flag = 0;
114         volatile unsigned int value = 0;
115         
116         /*      Disable Interrupts if necessary */
117         IFlag = FLASH_SaveDisableInterruptFlag();
118
119         /*      Set FLASH access mode to 16Bit Write Mode       */
120         FLASH_PrepareWriteHalfWordMode();
121                                         
122         secadr |= 0x0003;
123         
124         /*      Start FLASH Sector Erase Sequence       */
125         *hseq_1 = 0x00AA;
126         *hseq_2 = 0x0055;
127         *hseq_1 = 0x0080;
128         *hseq_1 = 0x00AA;
129         *hseq_2 = 0x0055;
130         *(unsigned  short int *)secadr = 0x0030;
131
132         /*      Wait for the Auto Algorithm to start    */
133         while( !( *(unsigned  short int *)secadr & SETIMR ) )
134         {
135                 /*      Feed the Hardware Watchdog      */
136                 HWWD_CL = 0;
137                 
138                 /*      Check for Pending Interrupts    */
139                 if( FLASH_CheckPendingInterrupt() )
140                 {               
141                         /*      Wait for Sector Erase Suspend   */
142                         FLASH_SuspendSectorErase(secadr);
143                         
144                 /*      Set FLASH access mode to 32Bit Read Mode        */
145                 FLASH_PrepareReadMode();
146                         
147                         /*      Restore the original Interrupt Flag     */
148                         FLASH_RestoreInterruptFlag(IFlag);
149                                                 
150                         /*      Keep on checking for pending Interrupts */
151                         while( FLASH_CheckPendingInterrupt() ) HWWD_CL = 0;
152                         
153                         /*      Disable Interrupts if necessary */
154                         IFlag = FLASH_SaveDisableInterruptFlag();
155                         
156                         /*      Set FLASH access mode to 16Bit Write Mode       */
157                 FLASH_PrepareWriteHalfWordMode();
158                                                 
159                         /*      Sector Erase Resume     */
160                         FLASH_ResumeSectorErase(secadr);
161                 }               
162         }
163
164         /*      Wait for the Auto Algorithm to finish   */
165         while( flag == 0 )
166         {
167                 /* Feed Hardware Watchdog */
168                 HWWD_CL = 0;
169
170                 /*      Check for Pending Interrupts    */
171                 if( FLASH_CheckPendingInterrupt() )
172                 {               
173                         /*      Sector Erase Suspend    */
174                         FLASH_SuspendSectorErase(secadr);
175                         
176                 /*      Set FLASH access mode to 32Bit Read Mode        */
177                 FLASH_PrepareReadMode();
178                                         
179                         /*      Restore the original Interrupt Flag     */
180                         FLASH_RestoreInterruptFlag(IFlag);
181                                                                         
182                         /*      Keep on checking for pending Interrupts */
183                         while( FLASH_CheckPendingInterrupt() ) HWWD_CL = 0;
184
185                         /*      Disable Interrupts if necessary */
186                         IFlag = FLASH_SaveDisableInterruptFlag();
187                         
188                         /*      Set FLASH access mode to 16Bit Write Mode       */
189                 FLASH_PrepareWriteHalfWordMode();
190                                                 
191                         /*      Sector Erase Resume     */
192                         FLASH_ResumeSectorErase(secadr);
193                 }               
194                 
195                         
196                 /*      Check the Hardware Sequence Flags       */                              
197                 if( ( *(unsigned short int *)secadr /* value */ & DPOLL ) )
198                 {
199                         flag = 1;
200                 }
201                 if( ( *(unsigned short int *)secadr /* value */ & TLOVER ) )
202                 {
203                         if( ( *(unsigned short int *)secadr /* value */ & DPOLL ) )
204                         {
205                                 flag = 1;
206                         }
207                         else
208                         {
209                                 /*      Reset FLASH     */
210                                 FLASH_ReadReset();
211                                 
212                                 flag = 2;
213                         }
214                 }
215         }
216         
217
218         /*      Restore the original Interrupt Flag     */
219         FLASH_RestoreInterruptFlag(IFlag);
220         
221         /*      Set FLASH access mode to 32Bit Read Mode        */
222         FLASH_PrepareReadMode();
223                 
224         return flag;
225 }
226
227 unsigned char FLASH_SectorBlankCheck(unsigned int secaddr, unsigned int size)
228 {
229         unsigned int count;
230         unsigned char empty_flag = 0;
231         unsigned int addr = secaddr;
232                 
233         /*      Clear FIXE bit to see FLASH memory content instead of fixed reset vector        */
234         FMCS_FIXE = 0;
235         
236         for(count = 0; count < size; count ++)
237         {
238                 /*      Clear Hardware Watchdog */
239                 HWWD_CL = 0;
240                 if( *(unsigned int *)addr != 0xFFFFFFFF ) empty_flag = 1;
241                 addr += 4;
242         }
243         
244         /*      Set FIXE bit to see fixed reset vector  */
245         FMCS_FIXE = 1;
246
247         if( empty_flag != 0 )
248         {
249                 return 2;
250         }
251         
252         return 1;
253 }
254
255 unsigned char FLASH_WriteHalfWord(unsigned int adr, unsigned short int data)
256 {
257         unsigned char flag = 0;
258
259         /*      Disable Interrupts if necessary */
260         IFlag = FLASH_SaveDisableInterruptFlag();
261                         
262         /*      Set FLASH access mode to 16Bit Write Mode       */
263         FLASH_PrepareWriteHalfWordMode();
264         
265         /*      Start Write FLASH Sequence      */
266         *hseq_1 = 0x00AA;
267         *hseq_2 = 0x0055;
268         *hseq_1 = 0x00A0;
269         *((volatile unsigned short int *)adr) = data;
270         
271         /*      Wait for the Auto Algorithm to finish   */
272         while( flag == 0 )
273         {
274                 /* Feed Hardware Watchdog */
275                 HWWD_CL = 0;
276                 
277                 if( ( *(volatile unsigned short int *)adr & DPOLL ) == (data & DPOLL) )
278                 {
279                         flag = 1;
280                 }
281                 if( ( *(volatile unsigned short int *)adr & TLOVER ) == TLOVER )
282                 {
283                         if( ( *(volatile unsigned short int *)adr & DPOLL ) == (data & DPOLL) )
284                         {
285                                 flag = 1;
286                         }
287                         else
288                         {
289                                 /*      Reset FLASH (keep in mind 16Bit access to FLASH)        */
290                                 *hseq_1 = 0x00F0;       // Keep in Mind (16Bit access)
291                                 
292                                 flag = 2;
293                         }
294                 }
295         }
296
297         /*      Set FLASH access mode to 32Bit Read Mode        */
298         FLASH_PrepareReadMode();
299         
300         /*      Restore the original Interrupt Flag     */
301         FLASH_RestoreInterruptFlag(IFlag);
302         
303         return flag;
304 }
305
306
307 unsigned char FLASH_ReadReset()
308 {
309         *hseq_1 = 0x00F0;
310         
311         return 1;
312 }
313
314 #pragma asm
315 _FLASH_SaveDisableInterruptFlag:
316         STM0 (R0)
317         MOV PS,R4
318         LDI     #0x00000010,R0  
319         AND R0,R4                       ; Store Original Flag
320         ANDCCR #0xFFFFFFEF      ; Clear Interrupt Flag
321         LDM0 (R0)       
322         RET
323 #pragma endasm
324
325
326 #pragma asm
327 _FLASH_RestoreInterruptFlag:
328         STM0 (R0)
329         MOV PS,R0                       ; Get current PS
330         OR R4,R0                        ; Set Flag as saved
331         MOV R0,PS                       ; Write back PS
332         LDM0 (R0)
333         RET
334 #pragma endasm
335
336
337 unsigned char FLASH_SuspendSectorErase(unsigned int secaddr)
338 {               
339         /* Write Sector Erase Suspend Command   */
340         *(volatile unsigned short int *)secaddr = 0x00B0;
341
342         /*      Wait for the FLASH macro to suspend sector erase        */              
343         while(!(*(unsigned short int *)secaddr /* value */ & DPOLL) && (*(unsigned short int *)secaddr /* value */ & SETIMR))
344         {
345                 HWWD_CL=0;
346         }
347         
348         return 1;
349 }
350
351 unsigned char FLASH_ResumeSectorErase(unsigned int secaddr)
352 {
353         /*      Write the Sector Erase Resume Command   */
354         *(volatile unsigned short int *)secaddr = 0x0030;
355         
356         /*      Wait for the FLASH Macro to resume sector erase */              
357         while((*(unsigned short int *)secaddr /*value */ & DPOLL) && !(*(unsigned short int *)secaddr /*value */ & SETIMR))
358         {
359                 HWWD_CL=0;
360         }
361         
362         return 1;               
363 }
364
365 unsigned char FLASH_CheckPendingInterrupt()
366 {
367         /*      Poll for Pending Interrupts which are needed here       */
368         if(TMCSR0_UF) return 1; /* in this sample the only interrupt source supervised is Reload Timer 0        */
369         
370         /*      and return 1 when an Interrupt is pending       */
371         return 0;
372 }