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