]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/atmel/at29cxxxx/v2_0/include/flash_at29cxxxx.inl
Initial revision
[karo-tx-redboot.git] / packages / devs / flash / atmel / at29cxxxx / v2_0 / include / flash_at29cxxxx.inl
1 #ifndef CYGONCE_DEVS_FLASH_ATMEL_AT29CXXXX_INL
2 #define CYGONCE_DEVS_FLASH_ATMEL_AT29CXXXX_INL
3 //==========================================================================
4 //
5 //      at29cxxxx.inl
6 //
7 //      Atmel AT29Cxxxx series flash driver
8 //
9 //==========================================================================
10 //####ECOSGPLCOPYRIGHTBEGIN####
11 // -------------------------------------------
12 // This file is part of eCos, the Embedded Configurable Operating System.
13 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
14 //
15 // eCos is free software; you can redistribute it and/or modify it under
16 // the terms of the GNU General Public License as published by the Free
17 // Software Foundation; either version 2 or (at your option) any later version.
18 //
19 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
22 // for more details.
23 //
24 // You should have received a copy of the GNU General Public License along
25 // with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 //
28 // As a special exception, if other files instantiate templates or use macros
29 // or inline functions from this file, or you compile this file and link it
30 // with other works to produce a work based on this file, this file does not
31 // by itself cause the resulting work to be covered by the GNU General Public
32 // License. However the source code for this file must still be made available
33 // in accordance with section (3) of the GNU General Public License.
34 //
35 // This exception does not invalidate any other reasons why a work based on
36 // this file might be covered by the GNU General Public License.
37 //
38 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39 // at http://sources.redhat.com/ecos/ecos-license/
40 // -------------------------------------------
41 //####ECOSGPLCOPYRIGHTEND####
42 //==========================================================================
43 //#####DESCRIPTIONBEGIN####
44 //
45 // Author(s):    gthomas
46 // Contributors: gthomas, jskov
47 // Date:         2001-02-21
48 // Purpose:      
49 // Description:  
50 //              
51 // Notes:        FLASH_P2V is not properly used.
52 //               Needs locking.
53 //####DESCRIPTIONEND####
54 //
55 //==========================================================================
56
57 #include <pkgconf/hal.h>
58 #include <cyg/hal/hal_arch.h>
59 #include <cyg/hal/hal_cache.h>
60 #include CYGHWR_MEMORY_LAYOUT_H
61
62 #define  _FLASH_PRIVATE_
63 #include <cyg/io/flash.h>
64
65
66 //----------------------------------------------------------------------------
67 // Common device details.
68 #define FLASH_Read_ID                   FLASHWORD( 0x90 )
69 #define FLASH_Read_ID_Exit              FLASHWORD( 0xF0 )
70 #define FLASH_Reset                     FLASHWORD( 0xFF )
71 #define FLASH_Program                   FLASHWORD( 0xA0 )
72 #define FLASH_Block_Erase               FLASHWORD( 0x30 )
73
74 #define FLASH_Data                      FLASHWORD( 0x80 ) // Data complement
75 #define FLASH_Busy                      FLASHWORD( 0x40 ) // "Toggle" bit
76 #define FLASH_Err                       FLASHWORD( 0x20 )
77 #define FLASH_Sector_Erase_Timer        FLASHWORD( 0x08 )
78
79 #define FLASH_Setup_Addr1               (0x5555)
80 #define FLASH_Setup_Addr2               (0x2AAA)
81 #define FLASH_Setup_Code1               FLASHWORD( 0xAA )
82 #define FLASH_Setup_Code2               FLASHWORD( 0x55 )
83 #define FLASH_Setup_Erase               FLASHWORD( 0x80 )
84
85 // Platform code must define the below
86 // #define CYGNUM_FLASH_INTERLEAVE      : Number of interleaved devices (in parallel)
87 // #define CYGNUM_FLASH_SERIES          : Number of devices in series
88 // #define CYGNUM_FLASH_BASE            : Address of first device
89 // And select one of the below device variants
90
91 #ifdef CYGPKG_DEVS_FLASH_ATMEL_AT29C040A
92 # define FLASH_BLOCK_SIZE               (0x10000*CYGNUM_FLASH_INTERLEAVE)
93 # define FLASH_NUM_REGIONS              (8)
94 # define CYGNUM_FLASH_BASE_MASK         (0xFFF80000u) // 512kB devices
95 # define CYGNUM_FLASH_WIDTH             (8)
96 # define CYGNUM_FLASH_BLANK             (1)
97 # define CYGNUM_FLASH_ID_MANUFACTURER   FLASHWORD(0x1F)
98 # define CYGNUM_FLASH_ID_DEVICE         FLASHWORD(0xA4)
99 #endif
100 #ifdef CYGPKG_DEVS_FLASH_ATMEL_AT29LV1024
101 # define FLASH_BLOCK_SIZE               (0x100*CYGNUM_FLASH_INTERLEAVE)
102 # define FLASH_NUM_REGIONS              (512)
103 # define CYGNUM_FLASH_BASE_MASK         (0xFFFe0000u) // 128kB devices
104 # define CYGNUM_FLASH_WIDTH             (16)
105 # define CYGNUM_FLASH_BLANK             (1)
106 # define CYGNUM_FLASH_ID_MANUFACTURER   FLASHWORD(0x1F)
107 # define CYGNUM_FLASH_ID_DEVICE         FLASHWORD(0x26)
108 #endif
109
110 #define FLASH_DEVICE_SIZE               (FLASH_BLOCK_SIZE*FLASH_NUM_REGIONS)
111 #define CYGNUM_FLASH_DEVICES            (CYGNUM_FLASH_INTERLEAVE*CYGNUM_FLASH_SERIES)
112
113 //----------------------------------------------------------------------------
114 // Now that device properties are defined, include magic for defining
115 // accessor type and constants.
116 #include <cyg/io/flash_dev.h>
117
118 //----------------------------------------------------------------------------
119 // Functions that put the flash device into non-read mode must reside
120 // in RAM.
121 void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));
122 int  flash_erase_block(void* block, unsigned int size) 
123     __attribute__ ((section (".2ram.flash_erase_block")));
124 int  flash_program_buf(void* addr, void* data, int len)
125     __attribute__ ((section (".2ram.flash_program_buf")));
126
127
128 //----------------------------------------------------------------------------
129 // Initialize driver details
130 int
131 flash_hwr_init(void)
132 {
133     flash_data_t id[2];
134
135     flash_dev_query(id);
136
137     // Check that flash_id data is matching the one the driver was
138     // configured for.
139     if (id[0] != CYGNUM_FLASH_ID_MANUFACTURER
140         || id[1] != CYGNUM_FLASH_ID_DEVICE)
141         return FLASH_ERR_DRV_WRONG_PART;
142
143     // Hard wired for now
144     flash_info.block_size = FLASH_BLOCK_SIZE;
145     flash_info.blocks = FLASH_NUM_REGIONS;
146     flash_info.start = (void *)CYGNUM_FLASH_BASE;
147     flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (FLASH_NUM_REGIONS * FLASH_BLOCK_SIZE * CYGNUM_FLASH_SERIES));
148     return FLASH_ERR_OK;
149 }
150
151 //----------------------------------------------------------------------------
152 // Map a hardware status to a package error
153 int
154 flash_hwr_map_error(int e)
155 {
156     return e;
157 }
158
159
160 //----------------------------------------------------------------------------
161 // See if a range of FLASH addresses overlaps currently running code
162 bool
163 flash_code_overlaps(void *start, void *end)
164 {
165     extern unsigned char _stext[], _etext[];
166
167     return ((((unsigned long)&_stext >= (unsigned long)start) &&
168              ((unsigned long)&_stext < (unsigned long)end)) ||
169             (((unsigned long)&_etext >= (unsigned long)start) &&
170              ((unsigned long)&_etext < (unsigned long)end)));
171 }
172
173 //----------------------------------------------------------------------------
174 // Flash Query
175 //
176 // Only reads the manufacturer and part number codes for the first
177 // device(s) in series. It is assumed that any devices in series
178 // will be of the same type.
179
180 void
181 flash_query(void* data)
182 {
183     volatile flash_data_t *ROM;
184     flash_data_t* id = (flash_data_t*) data;
185     int i;
186
187     ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE;
188
189     ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
190     ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
191     ROM[FLASH_Setup_Addr1] = FLASH_Read_ID;
192
193     // FIXME: 10ms delay
194     for (i = 10000; i > 0; i--);
195
196     // Manufacturers' code
197     id[0] = ROM[0];
198     // Part number
199     id[1] = ROM[1];
200
201     ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
202     ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
203     ROM[FLASH_Setup_Addr1] = FLASH_Read_ID_Exit;
204
205     // FIXME: 10ms delay
206     for (i = 10000; i > 0; i--);
207 }
208
209 //----------------------------------------------------------------------------
210 // Erase Block
211 int
212 flash_erase_block(void* block, unsigned int len)
213 {
214     volatile flash_data_t* ROM;
215     volatile flash_data_t* addr_ptr = (volatile flash_data_t*) block;
216     volatile flash_data_t* addr_ptr2;
217
218     int res = FLASH_ERR_OK;
219
220     while ((FLASH_ERR_OK == res) && (len > 0)) {
221         int len2, i, timeout;
222         flash_data_t state, prev_state;
223
224         // Base address of device(s) being programmed. 
225         ROM = (volatile flash_data_t*)((unsigned long)block & ~(FLASH_DEVICE_SIZE-1));
226
227         // Program data [byte] - 4 step sequence
228         ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
229         ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
230         ROM[FLASH_Setup_Addr1] = FLASH_Program;
231
232         addr_ptr2 = addr_ptr;
233         len2 = len;
234
235         // Always load 256 times
236         for (i = 0; i < 256; i++) {
237             *addr_ptr2++ = FLASH_BlankValue;
238         }
239
240         // Wait for completion (bit 6 stops toggling)
241         timeout = 5000000;
242         prev_state = *addr_ptr & FLASH_Busy;
243         while (true) {
244             state = *addr_ptr & FLASH_Busy;
245             if (prev_state == state) {
246                 break;
247             }
248             if (--timeout == 0) {
249                 res = FLASH_ERR_DRV_TIMEOUT;
250                 break;
251             }
252             prev_state = state;
253         }
254
255         // Verify loaded data bytes
256         for (i = 0; (len > 0) && (i < 256) ;) {
257             if (*addr_ptr != FLASH_BlankValue) {
258                 // Only update return value if erase operation was OK
259                 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
260                 break;
261             }
262             addr_ptr++;
263             len -= sizeof(*addr_ptr);
264             i += sizeof(*addr_ptr);
265         }
266     }
267
268     return FLASH_ERR_OK;
269 }
270
271 //----------------------------------------------------------------------------
272 // Program Buffer
273 int
274 flash_program_buf(void* addr, void* data, int len)
275 {
276     volatile flash_data_t* ROM;
277     volatile flash_data_t* addr_ptr = (volatile flash_data_t*) addr;
278     volatile flash_data_t* data_ptr = (volatile flash_data_t*) data;
279     volatile flash_data_t* addr_ptr2;
280     volatile flash_data_t* data_ptr2;
281
282     int res = FLASH_ERR_OK;
283
284 #if 0
285     CYG_ASSERT((unsigned long)data_ptr & (sizeof(flash_data_t)-1) == 0, 
286                "Data not properly aligned");
287     CYG_ASSERT((unsigned long)addr_ptr & (CYGNUM_FLASH_INTERLEAVE*sizeof(flash_data_t)-1) == 0, 
288                "Addr not properly aligned (to first interleaved device)");
289 #endif
290
291     while ((FLASH_ERR_OK == res) && (len > 0)) {
292         int len2, i, timeout;
293         flash_data_t state, prev_state;
294
295         // Base address of device(s) being programmed. 
296         ROM = (volatile flash_data_t*)((unsigned long)addr & ~(FLASH_DEVICE_SIZE-1));
297
298         // Program data [byte] - 4 step sequence
299         ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
300         ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
301         ROM[FLASH_Setup_Addr1] = FLASH_Program;
302
303         addr_ptr2 = addr_ptr;
304         data_ptr2 = data_ptr;
305         len2 = len;
306
307         // Always load 256 times
308         for (i = 0; i < 256; i++) {
309             if (len2 > 0) {
310                 *addr_ptr2++ = *data_ptr2++;
311                 len2 -= sizeof(*data_ptr2);
312             } else {
313                 *addr_ptr2++ = FLASH_BlankValue;
314             }
315         }
316
317         // Wait for completion (bit 6 stops toggling)
318         timeout = 5000000;
319         prev_state = *addr_ptr & FLASH_Busy;
320         while (true) {
321             state = *addr_ptr & FLASH_Busy;
322             if (prev_state == state) {
323                 break;
324             }
325             if (--timeout == 0) {
326                 res = FLASH_ERR_DRV_TIMEOUT;
327                 break;
328             }
329             prev_state = state;
330         }
331
332         // Verify loaded data bytes
333         for (i = 0; (len > 0) && (i < 256) ;) {
334             if (*addr_ptr != *data_ptr) {
335                 // Only update return value if erase operation was OK
336                 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
337                 break;
338             }
339             addr_ptr++;
340             data_ptr++;
341             len -= sizeof(*data_ptr);
342             i += sizeof(*data_ptr);
343         }
344     }
345
346
347     // Ideally, we'd want to return not only the failure code, but also
348     // the address/device that reported the error.
349     return res;
350 }
351
352 #endif // CYGONCE_DEVS_FLASH_ATMEL_AT29CXXXX_INL