]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/at91/v2_0/src/at91_flash.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / flash / arm / at91 / v2_0 / src / at91_flash.c
1 //==========================================================================
2 //
3 //      at91_flash.c
4 //
5 //      Flash programming for the at91 devices which have the 
6 //      Embedded Flash Controller.
7 //
8 //==========================================================================
9 //####ECOSGPLCOPYRIGHTBEGIN####
10 // -------------------------------------------
11 // This file is part of eCos, the Embedded Configurable Operating System.
12 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // Copyright (C) 2006 eCosCentric Ltd
14 // Copyright (C) 2006 Andrew Lunn (andrew.lunn@ascom.ch)
15 //
16 // eCos is free software; you can redistribute it and/or modify it under
17 // the terms of the GNU General Public License as published by the Free
18 // Software Foundation; either version 2 or (at your option) any later version.
19 //
20 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23 // for more details.
24 //
25 // You should have received a copy of the GNU General Public License along
26 // with eCos; if not, write to the Free Software Foundation, Inc.,
27 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 //
29 // As a special exception, if other files instantiate templates or use macros
30 // or inline functions from this file, or you compile this file and link it
31 // with other works to produce a work based on this file, this file does not
32 // by itself cause the resulting work to be covered by the GNU General Public
33 // License. However the source code for this file must still be made available
34 // in accordance with section (3) of the GNU General Public License.
35 //
36 // This exception does not invalidate any other reasons why a work based on
37 // this file might be covered by the GNU General Public License.
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    gthomas
44 // Contributors: gthomas, dmoseley, Andrew Lunn, Oliver Munz
45 // Date:         2000-07-26
46 // Purpose:      
47 // Description:  
48 //              
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53 #include <pkgconf/hal.h>
54 #include <pkgconf/devs_flash_at91.h>
55
56 #include <cyg/hal/hal_io.h>             
57 #include <cyg/hal/hal_intr.h>
58 #include <cyg/infra/cyg_ass.h>
59
60 #define  _FLASH_PRIVATE_
61 #include <cyg/io/flash.h>
62
63 #include <string.h>
64
65 #define FLASH_TIMEOUT       100000
66
67 #ifdef CYGBLD_DEV_FLASH_AT91_LOCKING
68 static cyg_uint32 sector_size;
69 #endif
70
71 // Disable the flash controller from erasing the page before
72 // programming it
73 static void 
74 flash_erase_before_write_disable (void)
75 {
76   cyg_uint32 fmr;
77   
78   HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, fmr);
79   fmr = fmr | AT91_MC_FMR_NEBP;
80   HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, fmr);
81 }
82
83 // Enable the flash controller to erase the page before programming
84 // it
85 static void 
86 flash_erase_before_write_enable (void) 
87 {
88   
89   cyg_uint32 fmr;
90
91   HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, fmr);
92   fmr = fmr & ~((cyg_uint32) AT91_MC_FMR_NEBP);
93   HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, fmr);
94 }
95
96 // Is the flash controller ready to accept the next command?
97 static __inline__ cyg_bool 
98 flash_controller_is_ready(void) 
99 CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
100
101 static __inline__ cyg_bool 
102 flash_controller_is_ready(void) 
103 {
104   cyg_uint32 fsr;
105   
106   HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
107   return (fsr & AT91_MC_FSR_FRDY ? true : false);
108 }
109
110 // Busy loop waiting for the controller to finish the command.
111 // Wait a maximum of timeout loops and then return an error.
112 static __inline__ int 
113 flash_wait_for_controller (cyg_uint32 timeout) 
114 CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
115
116 static __inline__ int 
117 flash_wait_for_controller (cyg_uint32 timeout)
118 {
119   while (!flash_controller_is_ready()){
120     timeout--;
121     if (!timeout) {
122       return FLASH_ERR_DRV_TIMEOUT;
123     }
124   }
125   return FLASH_ERR_OK;
126 }
127
128 // Execute one command on the flash controller. This code should
129 // probably not be in flash
130
131 static int 
132 flash_run_command(cyg_uint32 address, 
133                   cyg_uint32 command, 
134                   cyg_uint32 timeout) 
135 CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
136
137 static int 
138 flash_run_command(cyg_uint32 address, 
139                   cyg_uint32 command, 
140                   cyg_uint32 timeout) 
141 {
142   cyg_uint32 retcode;
143   cyg_uint32 fsr;
144   cyg_uint32 mask;
145   cyg_uint32 page;
146   
147   page = ((cyg_uint32) address - (cyg_uint32) flash_info.start) / 
148     flash_info.block_size;
149   
150   // Wait for the last command to finish
151   retcode = flash_wait_for_controller(timeout);
152   if (retcode != FLASH_ERR_OK){
153     return retcode;
154   }
155   
156   HAL_DISABLE_INTERRUPTS(mask);
157   
158   HAL_WRITE_UINT32(AT91_MC+AT91_MC_FCR, 
159                    command |
160                    ((page & AT91_MC_FCR_PAGE_MASK) << AT91_MC_FCR_PAGE_SHIFT) |
161                    AT91_MC_FCR_KEY);
162
163   retcode = flash_wait_for_controller(timeout);
164
165   HAL_RESTORE_INTERRUPTS(mask);
166
167   if (retcode != FLASH_ERR_OK){
168     return retcode;
169   }
170
171   // Check for an error
172   HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
173
174   if ((fsr & AT91_MC_FSR_LOCKE) == AT91_MC_FSR_LOCKE)
175     return FLASH_ERR_PROTECT;
176   if ((fsr & AT91_MC_FSR_PROGE) == AT91_MC_FSR_PROGE)
177     return FLASH_ERR_PROGRAM;
178
179   return FLASH_ERR_OK;
180 }
181
182 // The flash is embedded in the CPU package. So return the chip
183 // ID. This allows us to determine if the chip is one we support and
184 // the size of the flash
185 int flash_query(void *data) 
186 {
187   cyg_uint32 chipID1r;
188   
189   HAL_READ_UINT32(AT91_DBG+AT91_DBG_C1R, chipID1r);
190   
191   memcpy(data, &chipID1r, sizeof(chipID1r));
192   return FLASH_ERR_OK;
193 }
194
195 // Initialize the hardware. Make sure we have a flash device we know
196 // how to program and determine its size, the size of the blocks, and
197 // the number of blocks. The query function returns the chip ID 1
198 // register which tells us about the CPU we are running on, the flash
199 // size etc. Use this information to determine we have a valid setup.
200 int 
201 flash_hwr_init(void){
202
203   cyg_uint32 chipID1r;
204   cyg_uint32 flash_mode;
205   cyg_uint8  fmcn;
206   cyg_uint32 lock_bits;
207   
208   flash_query (&chipID1r);
209
210   if ((chipID1r & AT91_DBG_C1R_CPU_MASK) != AT91_DBG_C1R_ARM7TDMI)
211     goto out;
212
213   if (((chipID1r & AT91_DBG_C1R_ARCH_MASK) != AT91_DBG_C1R_ARCH_AT91SAM7Sxx) &&
214       ((chipID1r & AT91_DBG_C1R_ARCH_MASK) != AT91_DBG_C1R_ARCH_AT91SAM7Xxx))
215     goto out;
216   
217   if ((chipID1r & AT91_DBG_C1R_FLASH_MASK) == AT91_DBG_C1R_FLASH_0K)
218     goto out;
219   
220   switch (chipID1r & AT91_DBG_C1R_FLASH_MASK) {
221     case AT91_DBG_C1R_FLASH_32K:
222       flash_info.block_size = 128;
223       flash_info.blocks = 256;
224       lock_bits = 8;
225       break;
226     case AT91_DBG_C1R_FLASH_64K:
227       flash_info.block_size = 128;
228       flash_info.blocks = 512;
229       lock_bits = 16;
230       break;
231     case AT91_DBG_C1R_FLASH_128K:
232       flash_info.block_size = 256;
233       flash_info.blocks = 512;
234       lock_bits = 8;
235       break;
236     case AT91_DBG_C1R_FLASH_256K:
237       flash_info.block_size = 256;
238       flash_info.blocks = 1024;
239       lock_bits = 16;
240       break;
241     default:
242       goto out;
243   }
244   flash_info.buffer_size = 0;
245   flash_info.start = (void *) 0x00100000;
246   flash_info.end = (void *)(((cyg_uint32) flash_info.start) + 
247                             flash_info.block_size * flash_info.blocks);
248 #ifdef CYGBLD_DEV_FLASH_AT91_LOCKING
249   sector_size = flash_info.block_size * flash_info.blocks / lock_bits;
250 #endif
251   // Set the FLASH clock to 1.5 microseconds based on the MCLK.  This
252   // assumes the CPU is still running from the PLL clock as defined in
253   // the HAL CDL and the HAL startup code. 
254   fmcn = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / 1000000 * 1.5;
255   HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, flash_mode);
256   flash_mode = flash_mode & ~AT91_MC_FMR_FMCN_MASK;
257   flash_mode = flash_mode | (fmcn << AT91_MC_FMR_FMCN_SHIFT);
258   HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, flash_mode);
259   
260   return FLASH_ERR_OK;
261   
262  out:
263   (*flash_info.pf)("Can't identify FLASH, sorry, ChipID1 %x\n",
264                    chipID1r );
265   return FLASH_ERR_HWR;
266 }
267
268 // Erase a block. The flash controller does not have a command to
269 // erase a block. So instead we setup the controller to do a program
270 // writing all 0xff with an erase operation first.
271 int 
272 flash_erase_block (volatile unsigned long block) 
273 {
274   cyg_uint32 retcode;
275   cyg_uint32 *buffer;
276   cyg_uint32 *end;
277   
278   buffer = (cyg_uint32 *) block;
279   end = (cyg_uint32 *) (block + flash_info.block_size);
280   
281   while (buffer < end){ 
282     *buffer = (cyg_uint32) 0xffffffff;
283     buffer++;
284   }
285   
286   flash_erase_before_write_enable();
287   retcode = flash_run_command(block, 
288                               AT91_MC_FCR_START_PROG, 
289                               FLASH_TIMEOUT);
290   
291   return retcode;
292 }
293
294 // Write into the flash. The datasheet says that performing 8 or 16bit
295 // accesses results in unpredictable corruption. So the current code
296 // checks that these conditions are upheld. It would be possible to
297 // perform extra reads and masking operation to support writing to
298 // none word assigned addresses or not multiple or a word length.
299 int 
300 flash_program_buf (volatile unsigned long addr, unsigned long *data, int len)
301 {
302   cyg_uint32 retcode;
303   volatile unsigned long *target;
304   
305   CYG_ASSERT(len % 4 == 0, "Only word writes allowed by current code");
306   CYG_ASSERT(addr % 4 == 0, "Address must be word aligned for current code");
307   
308   target = (volatile unsigned long *)addr;
309   
310   while (len > 0) {
311     *target = *data;
312     data++;
313     target++;
314     len = len - sizeof(unsigned long);
315   }
316   
317   flash_erase_before_write_disable();
318   retcode = flash_run_command(addr, 
319                               AT91_MC_FCR_START_PROG, 
320                               FLASH_TIMEOUT);
321   
322   return retcode;
323 }
324
325 #ifdef CYGBLD_DEV_FLASH_AT91_LOCKING
326 // Unlock a block. This is not strictly possible, we can only lock and
327 // unlock sectors. This will unlock the sector which contains the
328 // block.
329 int
330 flash_unlock_block(volatile unsigned long block, int block_size, int blocks)
331 {
332   cyg_uint32 sector;
333   cyg_uint32 retcode;
334   cyg_uint32 status;
335   
336   sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) / 
337     sector_size;
338  
339   HAL_READ_UINT32(AT91_MC + AT91_MC_FSR, status);
340   
341   if (status & (1 << (sector + 16))){
342       retcode = flash_run_command(block, 
343                                   AT91_MC_FCR_UNLOCK, 
344                                   FLASH_TIMEOUT);
345       return retcode;
346   } else {
347     return FLASH_ERR_OK;
348   }
349 }
350
351 // Lock a block. This is not strictly possible, we can only lock and
352 // unlock sectors. This will lock the sector which contains the
353 // block.
354 int
355 flash_lock_block(volatile unsigned long block, int block_size, int blocks)
356 {
357   cyg_uint32 sector;
358   cyg_uint32 retcode;
359   cyg_uint32 status;
360   
361   sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) / 
362     sector_size;
363
364   HAL_READ_UINT32(AT91_MC + AT91_MC_FSR, status);
365   
366   if (!(status & (1 << (sector + 16)))){
367       retcode = flash_run_command(block, 
368                                   AT91_MC_FCR_LOCK, 
369                                   FLASH_TIMEOUT);
370       
371       return retcode;
372   } else {
373     return FLASH_ERR_OK;
374   }
375 }
376 #endif 
377   
378 // Map a hardware status to a package error. NOP since the errors are
379 // already mapped.
380 int flash_hwr_map_error(int err){
381
382   return err;
383 }
384
385 // See if a range of FLASH addresses overlaps currently running code
386 bool flash_code_overlaps(void *start, void *end){
387
388     extern char _stext[], _etext[];
389
390     return ((((unsigned long)&_stext >= (unsigned long)start) &&
391              ((unsigned long)&_stext < (unsigned long)end)) ||
392             (((unsigned long)&_etext >= (unsigned long)start) &&
393              ((unsigned long)&_etext < (unsigned long)end)));
394 }