]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/pid/v2_0/src/prog_flash.c
TX51 pre-release
[karo-tx-redboot.git] / packages / hal / arm / pid / v2_0 / src / prog_flash.c
1 //==========================================================================
2 //
3 //        prog_flash.c
4 //
5 //        ARM PID7 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:          1998-11-18
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
64 #ifndef FALSE
65 #define FALSE 0
66 #define TRUE  1
67 #endif
68
69 extern void diag_printf(const char *, ...);
70 int identify_FLASH(void);
71 void write_sector(int, char *);
72
73 char *flash_buffer =     (char *)0x60000;
74 char *flash_buffer_end = (char *)0x80000;
75
76 #ifdef BE_IMAGE
77 #define BUF(x) buf[x^3]
78 #else
79 #define BUF(x) buf[x]
80 #endif
81
82 // FUNCTIONS
83
84 externC void
85 cyg_package_start( void )
86 {
87 #ifdef CYGPKG_LIBC
88     cyg_iso_c_start();
89 #else
90     (void)main(0, NULL);
91 #endif
92 } // cyg_package_start()
93
94 int
95 main( int argc, char *argv[] )
96 {
97     int i;
98
99     diag_printf("FLASH here!\n");
100     while (identify_FLASH() == 0) {
101         diag_printf("... Please change FLASH jumper\n");
102         cyg_thread_delay(5*100);
103     }
104     diag_printf("About to program FLASH using data at %x..%x\n", flash_buffer, flash_buffer_end);
105     diag_printf("*** Press RESET now to abort!\n");
106     cyg_thread_delay(5*100);
107     diag_printf("\n");
108     diag_printf("...Programming FLASH\n");
109
110     i = 0;
111     while (flash_buffer < flash_buffer_end) {
112         write_sector(i++, flash_buffer);
113         flash_buffer += 256;
114     }
115     diag_printf("All done!\n");
116     while (1) ;
117 }
118
119 // Adapted from ARM sample code
120 #define SEQ_ADD1                0x5555
121 #define SEQ_ADD2                0xAAAA
122 #define START_CMD1              0xAA
123 #define START_CMD2              0x55
124 #define ID_CMD                  0x90
125 #define PROG_CMD                0xA0
126 #define STOP_CMD                0xF0
127
128 #define MAN_ATMEL               0x1F
129 #define ATMEL_AT29C040_ID       0X5B
130 #define ATMEL_AT29C040A_ID      0XA4
131 #define ATMEL_AT29C1024_ID      0X25
132 #define ATMEL_SECTOR_SIZE       256
133 #define ATMEL_MAX_SECTORS       2048
134
135 int manuf_code, device_code, sector_size, max_no_of_sectors, word_mode;
136 volatile char *FLASH = (volatile char *)0x04000000;
137
138 int
139 identify_FLASH(void )
140 {
141     // Enter Software Product Identification Mode
142     FLASH[SEQ_ADD1] = START_CMD1;
143     FLASH[SEQ_ADD2] = START_CMD2;
144     FLASH[SEQ_ADD1] = ID_CMD;
145
146     // Wait at least 10ms
147     cyg_thread_delay(2);
148
149     // Read Manufacturer and device code from the device
150     manuf_code = FLASH[0];
151     device_code = FLASH[1];
152
153     diag_printf("manuf: %x, device: %x\n", manuf_code, device_code);
154
155     // Exit Software Product Identification Mode
156     FLASH[SEQ_ADD1] = START_CMD1;
157     FLASH[SEQ_ADD2] = START_CMD2;
158     FLASH[SEQ_ADD1] = STOP_CMD;
159
160     // Wait at least 10ms
161     cyg_thread_delay(5);
162
163     if (manuf_code != MAN_ATMEL) {
164         diag_printf ( "Error: Wrong Manufaturer: %02x\n",manuf_code );
165         return (0);
166     }
167
168     switch (device_code) {
169     case  ATMEL_AT29C040A_ID:
170         diag_printf ("AT29C040A recognised\n");
171         sector_size = ATMEL_SECTOR_SIZE;
172         max_no_of_sectors = ATMEL_MAX_SECTORS;
173         word_mode = FALSE;
174         break;
175     case  ATMEL_AT29C1024_ID:
176         diag_printf ("AT29C1024 recognised\n");
177         sector_size = ATMEL_SECTOR_SIZE;
178         max_no_of_sectors = ATMEL_MAX_SECTORS;
179         word_mode = TRUE;
180         break;
181     default :
182         diag_printf ( "Error: Unsupported device: %02x\n", device_code);
183         return (0);
184     }
185     return (1);
186 }
187
188 void
189 write_sector(int num, char *buf)
190 {
191     int i, cnt;
192     volatile char *wrt = (volatile char *)&FLASH[num*sector_size];
193
194 //    diag_printf("Writing to %08x\n", wrt);
195     // Enter Program Mode
196     FLASH[SEQ_ADD1] = START_CMD1;
197     FLASH[SEQ_ADD2] = START_CMD2;
198     FLASH[SEQ_ADD1] = PROG_CMD;
199
200     // Note: write bytes as longs regardless of bus width
201     for (i = 0;  i < sector_size;  i++) {
202         wrt[i] = BUF(i);
203     }
204
205     // Wait for sector to program
206     cnt = 0;
207     i = sector_size - 1;
208     while (wrt[i] != BUF(i)) {
209         if (cnt++ > 0x01000000) break;
210     }
211 //    diag_printf("Out - i: %d, wrt[i] = %08X.%08X, BUF(i) = %08X, count = %x\n", i, &wrt[i], wrt[i], BUF(i), cnt);
212
213     // Verify
214     for (i = 0;  i < sector_size;  i++) {
215         for (cnt = 0;  cnt < 10;  cnt++) {
216             if (wrt[i] == BUF(i)) break;
217             cyg_thread_delay(1);
218         }
219         if (cnt == 10) {
220             diag_printf("Can't program at 0x%08X: %02X not %02X\n", wrt, *wrt, BUF(0));
221         }
222     }
223 }