]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/integrator/v2_0/src/prog_flash.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / integrator / v2_0 / src / prog_flash.c
1 //==========================================================================
2 //
3 //        prog_flash.c
4 //
5 //        ARM INTEGRATOR 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:  Philippe Robin
45 // Date:          November 7, 2000
46 // Description:   Tool used to program onboard FLASH image
47 //####DESCRIPTIONEND####
48
49 //
50 // This program will program the FLASH on the PID board
51 // It is similar to 'flash' (which also downloads S records) but it always
52 // programs from a fixed buffer.  This is sufficient to load/update the GDB
53 // stubs on the board.
54 //
55
56 #include <pkgconf/libc.h>   // Configuration header
57
58 #include <cyg/kernel/kapi.h>
59 #include <stdlib.h>
60 #include <ctype.h>
61 #include <cyg/infra/testcase.h>
62 #include <sys/cstartup.h>
63 #include <cyg/hal/hal_integrator.h>
64
65 #ifndef FALSE
66 #define FALSE 0
67 #define TRUE  1
68 #endif
69
70
71 #define INVALID_FTYPE           0x00000000
72 #define UNKNOWN_FTYPE           0xFFFFFFFF
73 #define ATMEL_FTYPE             0x00000001
74 #define INTEL_FTYPE             0x00000002
75
76 #define FLASH_TYPE_MASK         (ATMEL_FTYPE | INTEL_FTYPE)
77
78 // On Some platforms Boot and program flash may be part of the same device
79 #define INTEGRATED_FTYPE        0x80000000
80 #define BOOT_FTYPE              0x40000000
81 #define APP_FTYPE               0x20000000
82
83 #define FLASH_USAGE_MASK        (BOOT_FTYPE | APP_FTYPE)
84
85 #define DEFAULT_FLASH_MASK 0xFFFFFFF8
86 #define FLASH_BLOCK_SIZE        0x00020000      // 128Kb
87 #define EPROM_BASE              0x20000000
88 #define EPROM_SIZE              0x00080000      // 512Kb
89 #define FLASH_BASE              0x24000000
90 #define FLASH_SIZE              0x02000000      // 32Mb
91
92 typedef struct flashType {
93     char *base;                 // Base Address of flash
94     char *physicalBase;         // before mem initialisation
95     unsigned int size;          // Size of flash, in bytes
96     unsigned int type;          // Atmel / Intel (CFI) / Unknown
97     unsigned int writeSize;     // Size of physical block
98     unsigned int eraseSize;     // Size of block erase
99     unsigned int logicalSize;   // Size of logical block
100     char *ident;                // identification string
101 } tFlash;
102
103 tFlash Integrator_Flash[2] =
104 {
105     {
106         (char *)EPROM_BASE,             // Base Address of flash
107         (char *)EPROM_BASE,             // Physical Address of flash
108         EPROM_SIZE,                     // Size of flash, in bytes (512K)
109         BOOT_FTYPE | ATMEL_FTYPE,       // Flash type
110         FLASH_BLOCK_SIZE,       // Size of physical block
111         FLASH_BLOCK_SIZE,       // Size of block erase
112         FLASH_BLOCK_SIZE,       // Size of logical block
113         "Atmel",                // Null terminated Info string
114     },
115     {
116         (char *)FLASH_BASE,     // Base Address of flash
117         (char *)FLASH_BASE,     // Physical Address of flash
118         FLASH_SIZE,             // Size of flash, in bytes
119         APP_FTYPE | INTEL_FTYPE,        // Flash type
120         FLASH_BLOCK_SIZE,       // Size of physical block
121         FLASH_BLOCK_SIZE,       // Size of block erase
122         FLASH_BLOCK_SIZE,       // Size of logical block
123         "Intel 28F320S3",       // Null terminated Info string
124    }
125 };
126
127
128 extern void diag_printf(const char *, ...);
129 int identify_FLASH(void);
130 void write_sector(int, char *);
131
132 char *flash_buffer =     (char *)0x60000;
133 char *flash_buffer_end = (char *)0x80000;
134
135 #ifdef BE_IMAGE
136 #define BUF(x) buf[x^3]
137 #else
138 #define BUF(x) buf[x]
139 #endif
140
141 // FUNCTIONS
142
143 externC void
144 cyg_package_start( void )
145 {
146 #ifdef CYGPKG_LIBC
147     cyg_iso_c_start();
148 #else
149     (void)main(0, NULL);
150 #endif
151 } // cyg_package_start()
152
153 int
154 main( int argc, char *argv[] )
155 {
156     int i;
157
158     diag_printf("FLASH here!\n");
159     while (identify_FLASH() == 0) {
160         diag_printf("... Please change FLASH jumper\n");
161         cyg_thread_delay(5*100);
162     }
163     diag_printf("About to program FLASH using data at %x..%x\n", flash_buffer, flash_buffer_end);
164     diag_printf("*** Press RESET now to abort!\n");
165     cyg_thread_delay(5*100);
166     diag_printf("\n");
167     diag_printf("...Programming FLASH\n");
168
169     i = 0;
170     while (flash_buffer < flash_buffer_end) {
171         write_sector(i++, flash_buffer);
172         flash_buffer += 256;
173     }
174     diag_printf("All done!\n");
175     while (1) ;
176 }
177
178 // Adapted from ARM sample code
179 #define SEQ_ADD1                0x5555
180 #define SEQ_ADD2                0x2aaa
181 #define START_CMD1              0xaaaaaaaa
182 #define START_CMD2              0x55555555
183 #define ID_CMD                  0x90909090
184 #define PROG_CMD                0xA0
185 #define STOP_CMD                0xf0f0f0f0
186
187 #define MAN_ATMEL               0x1F
188 #define ATMEL_AT29C040_ID       0X5B
189 #define ATMEL_AT29C040A_ID      0XA4
190 #define ATMEL_AT29C1024_ID      0X25
191 #define ATMEL_SECTOR_SIZE       256
192 #define ATMEL_MAX_SECTORS       2048
193
194 #define MAN_INTEL               0xB0
195 #define INTEL_28F320S3_ID       0xD4
196
197 int manuf_code, device_code;
198 int sector_size, max_no_of_sectors, word_mode;
199 volatile unsigned int *FLASH = (volatile unsigned int *)0x24000000;
200
201 int
202 identify_FLASH(void )
203 {
204     unsigned int *ptr = (unsigned int *)FLASH;
205
206     HAL_FLASH_WRITE_ENABLE();
207
208     // Enter Software Product Identification Mode
209     FLASH[SEQ_ADD1] = START_CMD1;
210     FLASH[SEQ_ADD2] = START_CMD2;
211     FLASH[SEQ_ADD1] = ID_CMD;
212
213     // Wait at least 10ms
214     cyg_thread_delay(4);
215
216     // Read Manufacturer and device code from the device
217     manuf_code   = *ptr++ & 0xff;
218     device_code  = *ptr & 0xff;
219     
220     diag_printf("manuf: 0x%x, device: 0x%x\n", manuf_code, device_code);
221
222     // Exit Software Product Identification Mode
223     FLASH[SEQ_ADD1] = START_CMD1;
224     FLASH[SEQ_ADD2] = START_CMD2;
225     FLASH[SEQ_ADD1] = STOP_CMD;
226
227     // Wait at least 10ms
228     cyg_thread_delay(5);
229
230     HAL_FLASH_WRITE_DISABLE();
231
232     if (manuf_code != MAN_ATMEL || manuf_code != MAN_INTEL) {
233         diag_printf ( "Error: Wrong Manufaturer: %02x\n", manuf_code );
234         return (0);
235     }
236
237     switch (device_code) {
238     case  ATMEL_AT29C040A_ID:
239         diag_printf ("AT29C040A recognised\n");
240         sector_size = ATMEL_SECTOR_SIZE;
241         max_no_of_sectors = ATMEL_MAX_SECTORS;
242         word_mode = FALSE;
243         break;
244
245     case  ATMEL_AT29C1024_ID:
246         diag_printf ("AT29C1024 recognised\n");
247         sector_size = ATMEL_SECTOR_SIZE;
248         max_no_of_sectors = ATMEL_MAX_SECTORS;
249         word_mode = TRUE;
250         break;
251
252     case  INTEL_28F320S3_ID:
253         diag_printf ("INTEL_28F320S3 recognised\n");
254         sector_size = FLASH_BLOCK_SIZE;
255         //        max_no_of_sectors = ATMEL_MAX_SECTORS;
256         word_mode = TRUE;
257         break;
258
259     default :
260         diag_printf ( "Error: Unsupported device: %02x\n", device_code);
261         return (0);
262     }
263     return (1);
264 }
265
266 void
267 write_sector(int num, char *buf)
268 {
269     int i, cnt;
270     volatile char *wrt = (volatile char *)&FLASH[num*sector_size];
271
272 //    diag_printf("Writing to %08x\n", wrt);
273     // Enter Program Mode
274     FLASH[SEQ_ADD1] = START_CMD1;
275     FLASH[SEQ_ADD2] = START_CMD2;
276     FLASH[SEQ_ADD1] = PROG_CMD;
277
278     // Note: write bytes as longs regardless of bus width
279     for (i = 0;  i < sector_size;  i++) {
280         wrt[i] = BUF(i);
281     }
282
283     // Wait for sector to program
284     cnt = 0;
285     i = sector_size - 1;
286     while (wrt[i] != BUF(i)) {
287         if (cnt++ > 0x01000000) break;
288     }
289 //    diag_printf("Out - i: %d, wrt[i] = %08X.%08X, BUF(i) = %08X, count = %x\n", i, &wrt[i], wrt[i], BUF(i), cnt);
290
291     // Verify
292     for (i = 0;  i < sector_size;  i++) {
293         for (cnt = 0;  cnt < 10;  cnt++) {
294             if (wrt[i] == BUF(i)) break;
295             cyg_thread_delay(1);
296         }
297         if (cnt == 10) {
298             diag_printf("Can't program at 0x%08X: %02X not %02X\n", wrt, *wrt, BUF(0));
299         }
300     }
301 }