]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/arm/edb7xxx/v2_0/misc/prog_flash.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / edb7xxx / v2_0 / misc / prog_flash.c
1 //==========================================================================
2 //
3 //        prog_flash.c
4 //
5 //        Cirrus CL7211 eval board FLASH program tool
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):     gthomas
44 // Contributors:  gthomas
45 // Date:          1999-05-12
46 // Description:   Tool used to program onboard FLASH image
47 //####DESCRIPTIONEND####
48
49 //
50 // This program will program the FLASH on the CL7211 board from a fixed buffer
51 //
52
53 #include <pkgconf/kernel.h>   // Configuration header
54 #include <cyg/kernel/kapi.h>
55 #include <cyg/infra/diag.h>
56 #include <cyg/hal/hal_cache.h>
57
58 #ifndef FALSE
59 #define FALSE 0
60 #define TRUE  1
61 #endif
62
63 #define STACK_SIZE 4096
64 static char stack[STACK_SIZE];
65 static cyg_thread thread_data;
66 static cyg_handle_t thread_handle;
67
68 void identify_FLASH(void);
69 int  write_flash(long *data, volatile long *mem);
70 int  erase_sector(volatile long *mem);
71
72 // Note: these are mapped addresses
73 //  0xE0000000 = ROM Bank 0
74 //  0xF0000000 = ROM Bank 1
75 volatile unsigned long *FLASH = (volatile unsigned long *)0xE0000000;
76
77 long *flash_buffer =     (long *)0x60000;
78 long *flash_buffer_end = (long *)0x64000;
79 long *ROM_address =      (long *)0xE07E0000;
80
81 // Adapted from Cirrus sample code
82 #define ATMEL_SEQ_ADD1                0x00015554>>2
83 #define ATMEL_SEQ_ADD2                0x0000AAA8>>2
84 #define ATMEL_START_CMD1              0xAAAAAAAA
85 #define ATMEL_START_CMD2              0x55555555
86 #define ATMEL_ID_CMD                  0x90909090
87 #define ATMEL_PROG_CMD                0xA0A0A0A0
88 #define ATMEL_ERASE_CMD               0x80808080
89 #define ATMEL_SECTOR_ERASE_CMD        0x30303030
90 #define ATMEL_STOP_CMD                0xF0F0F0F0
91 #define ATMEL_BUSY_TOGGLE             0x00400040
92 #define ATMEL_ERASE_TOGGLE            0x00440044
93
94 #define ATMEL_MANUF                   0x1F
95 #define ATMEL_AT29C040_ID             0X5B
96 #define ATMEL_AT29C040A_ID            0XA4
97 #define ATMEL_AT29C1024_ID            0X25
98 #define ATMEL_SECTOR_SIZE             256
99 #define ATMEL_MAX_SECTORS             2048
100
101 #define INTEL_MANUF                   0x0089
102 #define INTEL_STOP_CMD                0x00FF00FF
103 #define INTEL_PROG_CMD                0x00400040
104 #define INTEL_ERASE_CMD               0x00200020
105 #define INTEL_ERASE_CONFIRM           0x00D000D0
106 #define INTEL_READ_STATUS             0x00700070
107 #define INTEL_CLEAR_STATUS            0x00500050
108 #define INTEL_SB_WSMS                 0x00800080  // Write state machine = ready
109 #define INTEL_SB_ERASE_ERROR          0x00200020  // Erase failure
110 #define INTEL_SB_PROG_ERROR           0x00100010  // Programming failure
111
112 #define ERASE_TIMEOUT                 10          // seconds
113
114 int manuf_code, device_code, sector_size, max_no_of_sectors, word_mode;
115
116 // FUNCTIONS
117
118 static void
119 cyg_test_exit(void)
120 {
121     while (TRUE) ;
122 }
123
124 static void
125 program_flash(cyg_addrword_t arg)
126 {
127     diag_printf("PROGRAM FLASH here!\n");
128     HAL_UCACHE_SYNC();     // ROM space is marked cacheable which causes problems!
129     HAL_UCACHE_DISABLE();  // So, just disable caches.
130     identify_FLASH();
131     diag_printf("About to program FLASH using data at %x..%x\n", flash_buffer, flash_buffer_end);
132     diag_printf("*** Press RESET now to abort!\n");
133     cyg_thread_delay(5*100);
134     diag_printf("\n");
135     diag_printf("... Erase sector\n");
136     if (erase_sector(ROM_address)) {
137         diag_printf("... Programming FLASH\n");
138         while (flash_buffer < flash_buffer_end) {
139             if (!write_flash(flash_buffer++, ROM_address++)) break;
140         }
141     }
142     
143     // Exit Program Mode
144     switch (manuf_code) {
145     case ATMEL_MANUF:
146         FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
147         FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
148         FLASH[ATMEL_SEQ_ADD1] = ATMEL_STOP_CMD;
149         break;
150     case INTEL_MANUF:
151         FLASH[0] = INTEL_STOP_CMD;
152         break;
153     }
154     diag_printf("All done!\n");
155     cyg_test_exit();
156 }
157
158 void
159 identify_FLASH(void )
160 {
161     // Enter Software Product Identification Mode
162     FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
163     FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
164     FLASH[ATMEL_SEQ_ADD1] = ATMEL_ID_CMD;
165
166     // Wait at least 10ms
167     cyg_thread_delay(2);
168
169     // Read Manufacturer and device code from the device
170     manuf_code = FLASH[0] >> 16;
171     device_code = FLASH[1] >> 16;
172
173     diag_printf("manufacturer: 0x%04x, device: 0x%04x\n", manuf_code, device_code);
174
175     // Exit Software Product Identification Mode
176     switch (manuf_code) {
177     case ATMEL_MANUF:
178         FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
179         FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
180         FLASH[ATMEL_SEQ_ADD1] = ATMEL_STOP_CMD;
181         break;
182     case INTEL_MANUF:
183         FLASH[0] = INTEL_STOP_CMD;
184         break;
185     default:
186         diag_printf("Unrecognized FLASH manufacturer - I give up!\n");
187         cyg_test_exit();
188     }
189 }
190
191 void
192 spin(void)
193 {
194     volatile int i;
195     for (i = 0;  i < 100;  i++) ;
196 }
197
198 int
199 write_flash(long *data, volatile long *mem)
200 {
201     long data1, data2;
202     long status;
203     int timer;
204     switch (manuf_code) {
205     case ATMEL_MANUF:
206         // Enter Program Mode
207         FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
208         FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
209         FLASH[ATMEL_SEQ_ADD1] = ATMEL_PROG_CMD;
210         // Send data to selected address
211         *mem = *data;
212         while (TRUE) {
213             data1 = *mem;  // Read cell back twice
214             data2 = *mem;
215             // Bit 6 toggles between reads while programming in progress
216             if ((data1 & ATMEL_BUSY_TOGGLE) == (data2 & ATMEL_BUSY_TOGGLE)) break;
217         }
218         break;
219     case INTEL_MANUF:
220         // Clear current errors
221         FLASH[0] = INTEL_CLEAR_STATUS;
222         // Issue program command
223         FLASH[0] = INTEL_PROG_CMD;
224         // Send data to selected address
225         *mem = *data;
226         timer = 10000;
227         // Read the status register to wait for programming complete
228         do {
229             spin();
230             status = FLASH[0];
231         } while (((status & INTEL_SB_WSMS) != INTEL_SB_WSMS) &&
232                  (--timer > 0));
233         // Check for errors
234         if (timer == 0) {
235             diag_printf("Programming at 0x%08x timed out - status: 0x%08x\n", mem, status);
236         }
237         if ((status & INTEL_SB_PROG_ERROR) != 0) {
238             diag_printf("Device reports programming error at 0x%08x - status: 0x%08x\n", mem, status);
239         }
240         // Exit program mode
241         FLASH[0] = INTEL_STOP_CMD;
242         break;
243     }
244     if (*mem != *data) {
245         diag_printf("Programming failed at 0x%08x - write: 0x%08x, read: 0x%08x\n",
246                     mem, *data, *mem);
247         return (FALSE);
248     }
249     return (TRUE);
250 }
251
252 int
253 erase_sector(volatile long *mem)
254 {
255     long data1, data2;
256     long status;
257     int timer;
258     switch (manuf_code) {
259     case ATMEL_MANUF:
260         // Erase sector command
261         FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
262         FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
263         FLASH[ATMEL_SEQ_ADD1] = ATMEL_ERASE_CMD;
264         FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
265         FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
266         *mem = ATMEL_SECTOR_ERASE_CMD;
267         while (TRUE) {
268             data1 = *mem;  // Read cell back twice
269             data2 = *mem;
270             // Bits 6+2 toggle between reads while programming in progress
271             if ((data1 & ATMEL_ERASE_TOGGLE) == (data2 & ATMEL_ERASE_TOGGLE)) break;
272         }
273         break;
274     case INTEL_MANUF:
275         // Clear current errors
276         FLASH[0] = INTEL_CLEAR_STATUS;
277         // Issue erase block command
278         FLASH[0] = INTEL_ERASE_CMD;
279         *mem = INTEL_ERASE_CONFIRM;
280         timer = ERASE_TIMEOUT*50;
281         // Read the status register while erase in progress
282         do {
283             cyg_thread_delay(2);
284             status = FLASH[0];
285         } while (((status & INTEL_SB_WSMS) != INTEL_SB_WSMS) &&
286                  (--timer > 0));
287         // Check for errors
288         if (timer == 0) {
289             diag_printf("Erase not complete after %d seconds - status: 0x%08x\n", 
290                         ERASE_TIMEOUT, status);
291         }
292         if ((status & INTEL_SB_ERASE_ERROR) != 0) {
293             diag_printf("Device reports erase error - status: 0x%08x\n", status);
294         }
295         // Exit erase mode
296         FLASH[0] = INTEL_STOP_CMD;
297         break;
298     }
299     if (*mem != 0xFFFFFFFF) {
300         diag_printf("Erase failed at 0x%08x - read: 0x%08x\n",
301                     mem, *mem);
302         return (FALSE);
303     }
304     return (TRUE);
305 }
306
307 externC void
308 cyg_start( void )
309 {
310     // Create a main thread, so we can run the scheduler and have time 'pass'
311     cyg_thread_create(10,                // Priority - just a number
312                       program_flash,     // entry
313                       1,                 // index
314                       "program_thread",  // Name
315                       &stack[0],         // Stack
316                       STACK_SIZE,        // Size
317                       &thread_handle,    // Handle
318                       &thread_data       // Thread data structure
319             );
320     cyg_thread_resume(thread_handle);  // Start it
321     cyg_scheduler_start();
322 } // cyg_package_start()
323