]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/mxc/v2_0/src/mxcflash_wrapper.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / src / mxcflash_wrapper.c
1 //==========================================================================
2 //
3 //      mxcflash_wrapper.c
4 //
5 //      Flash programming wrapper to support both NOR and NAND flashes
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):    Kevin Zhang <k.zhang@freescale.com>
44 // Contributors: Kevin Zhang <k.zhang@freescale.com>
45 // Date:         2006-01-23
46 // Purpose:
47 // Description:
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53 #include <pkgconf/hal.h>
54 #include <cyg/hal/hal_arch.h>
55 #include <cyg/hal/hal_cache.h>
56 #include <cyg/hal/hal_misc.h>
57 #include <redboot.h>
58
59 extern void norflash_query(void* data);
60 extern int norflash_hwr_init(void);
61 extern int norflash_hwr_map_error(int e);
62 extern bool norflash_code_overlaps(void *start, void *end);
63 extern int norflash_erase_block(void* block, unsigned int size);
64 extern int norflash_program_buf(void* addr, void* data, int len);
65 extern int norflash_lock_block(void* block);
66 extern int norflash_unlock_block(void* block, int block_size, int blocks);
67
68 extern void nandflash_query(void* data);
69 extern int nandflash_hwr_init(void);
70 extern int nandflash_hwr_map_error(int e);
71 extern bool nandflash_code_overlaps(void *start, void *end);
72 extern int nandflash_erase_block(void* block, unsigned int size);
73 extern int nandflash_program_buf(void* addr, void* data, int len);
74 extern int nandflash_lock_block(void* block);
75 extern int nandflash_unlock_block(void* block, int block_size, int blocks);
76 extern void mxc_nfc_print_info(void);
77 extern int nandflash_read_buf(void* addr, void* data, int len);
78
79 extern void mmcflash_query(void* data);
80 extern int mmcflash_hwr_init(void);
81 extern int mmcflash_hwr_map_error(int e);
82 extern bool mmcflash_code_overlaps(void *start, void *end);
83 extern int mmcflash_erase_block(void* block, unsigned int size);
84 extern int mmcflash_program_buf(void* addr, void* data, int len);
85 extern int mmcflash_lock_block(void* block);
86 extern int mmcflash_unlock_block(void* block, int block_size, int blocks);
87 extern void mxc_mmc_print_info(void);
88 extern int mmcflash_read_buf(void* addr, void* data, int len);
89
90 extern void ata_hwr_init(void);
91
92 extern void spi_norflash_query(void* data);
93 extern int spi_norflash_hwr_init(void);
94 extern int spi_norflash_hwr_map_error(int e);
95 extern bool spi_norflash_code_overlaps(void *start, void *end);
96 extern int spi_norflash_erase_block(void* block, unsigned int size);
97 extern int spi_norflash_program_buf(void* addr, void* data, int len);
98 extern int spi_norflash_lock_block(void* block);
99 extern int spi_norflash_unlock_block(void* block, int block_size, int blocks);
100 extern int spi_norflash_read_buf(void* addr, void* data, int len);
101
102 #ifndef IS_BOOTING_FROM_SPI_NOR()
103 #define IS_BOOTING_FROM_SPI_NOR()   0
104 #endif
105 #ifndef IS_FIS_FROM_SPI_NOR()
106 #define IS_FIS_FROM_SPI_NOR()       0
107 #endif
108
109 static int mxc_flash_warning_done = 0;
110
111 void flash_query(void* data)
112 {
113     if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
114 #ifdef MXCFLASH_SELECT_NOR
115         norflash_query(data);
116 #endif
117     } else if (IS_BOOTING_FROM_SPI_NOR() || IS_FIS_FROM_SPI_NOR()){
118 #ifdef IMXFLASH_SELECT_SPI_NOR
119         spi_norflash_query(data);
120 #endif
121     } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
122         nandflash_query(data);
123     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
124 #ifdef MXCFLASH_SELECT_MMC
125         mmcflash_query(data);
126 #endif
127     } else {
128         if (!mxc_flash_warning_done) {
129             mxc_flash_warning_done = 1;
130             diag_printf("1: Use \"factive\" to select a boot type such as NAND|NOR|MMC|...\n");
131         }
132     }
133 }
134
135 int flash_hwr_init(void)
136 {
137     if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
138 #ifdef MXCFLASH_SELECT_NOR
139         return norflash_hwr_init();
140 #endif
141     } else if (IS_BOOTING_FROM_SPI_NOR() || IS_FIS_FROM_SPI_NOR()){
142 #ifdef IMXFLASH_SELECT_SPI_NOR
143 #ifdef MXCFLASH_SELECT_ATA
144         /* ATA support is needed only for SPI boot */
145         ata_hwr_init();
146 #endif
147         return spi_norflash_hwr_init();
148 #endif
149     } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
150 #ifdef MXCFLASH_SELECT_NAND
151         return nandflash_hwr_init();
152 #endif
153     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
154 #ifdef MXCFLASH_SELECT_MMC
155         return mmcflash_hwr_init();
156 #endif
157     } else {
158         if (!mxc_flash_warning_done)
159             mxc_flash_warning_done = 1;
160         diag_printf("2: Use \"factive\" to select a boot type such as NAND|NOR|MMC|...\n");
161         return -1;
162     }
163
164     return -1;
165 }
166
167 int flash_hwr_map_error(int e)
168 {
169     if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
170 #ifdef MXCFLASH_SELECT_NOR
171         return norflash_hwr_map_error(e);
172 #endif
173     } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
174 #ifdef MXCFLASH_SELECT_NAND
175         return nandflash_hwr_map_error(e);
176 #endif
177     } else if (IS_BOOTING_FROM_SPI_NOR() || IS_FIS_FROM_SPI_NOR()){
178 #ifdef IMXFLASH_SELECT_SPI_NOR
179         return spi_norflash_hwr_map_error(e);
180 #endif
181     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
182 #ifdef MXCFLASH_SELECT_MMC
183         return mmcflash_hwr_map_error(e);
184 #endif
185     }
186     return e;
187 }
188
189 bool flash_code_overlaps(void *start, void *end)
190 {
191     if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
192 #ifdef MXCFLASH_SELECT_NOR
193         return norflash_code_overlaps(start, end);
194 #endif
195     } else if (IS_BOOTING_FROM_SPI_NOR() || IS_FIS_FROM_SPI_NOR()){
196 #ifdef IMXFLASH_SELECT_SPI_NOR
197         return spi_norflash_code_overlaps(start, end);
198 #endif
199     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
200 #ifdef MXCFLASH_SELECT_MMC
201         return mmcflash_code_overlaps(start, end);
202 #endif
203     } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()){
204 #ifdef MXCFLASH_SELECT_NAND
205         return nandflash_code_overlaps(start, end);
206 #endif
207     } else {
208         diag_printf("Error %d: where is fis\n", __LINE__);
209         return true;
210     }
211     return false;
212 }
213
214 int flash_erase_block(void* block, unsigned int size)
215 {
216     if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
217 #ifdef MXCFLASH_SELECT_NOR
218         return norflash_erase_block(block, size);
219 #endif
220     } else if (IS_BOOTING_FROM_SPI_NOR() || IS_FIS_FROM_SPI_NOR()){
221 #ifdef IMXFLASH_SELECT_SPI_NOR
222         return spi_norflash_erase_block(block, size);
223 #endif
224     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
225 #ifdef MXCFLASH_SELECT_MMC
226         return mmcflash_erase_block(block, size);
227 #endif
228     } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()){
229 #ifdef MXCFLASH_SELECT_NAND
230         return nandflash_erase_block(block, size);
231 #endif
232     } else {
233         diag_printf("Error %d: where is fis\n", __LINE__);
234         return -1;
235     }
236     return 0;
237 }
238
239 int flash_program_buf(void* addr, void* data, int len)
240 {
241     if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
242 #ifdef MXCFLASH_SELECT_NOR
243         return norflash_program_buf(addr, data, len);
244 #endif
245     } else if (IS_BOOTING_FROM_SPI_NOR() || IS_FIS_FROM_SPI_NOR()){
246 #ifdef IMXFLASH_SELECT_SPI_NOR
247         return spi_norflash_program_buf(addr, data, len);
248 #endif
249     } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
250 #ifdef MXCFLASH_SELECT_NAND
251         return nandflash_program_buf(addr, data, len);
252 #endif
253     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
254 #ifdef MXCFLASH_SELECT_MMC
255         return mmcflash_program_buf(addr, data, len);
256 #else
257         return 0;
258 #endif
259     } else {
260         return -1;
261     }
262 }
263
264 int flash_read_buf(void* addr, void* data, int len)
265 {
266     if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()){
267 #ifdef MXCFLASH_SELECT_NAND
268         return nandflash_read_buf(addr, data, len);
269 #endif
270     } else if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
271 #ifdef MXCFLASH_SELECT_NOR
272         memcpy(data, addr, len);
273         return 0;
274 #endif
275     } else if (IS_BOOTING_FROM_SPI_NOR() || IS_FIS_FROM_SPI_NOR()){
276 #ifdef IMXFLASH_SELECT_SPI_NOR
277         return spi_nor_read(addr, data, len);
278 #endif
279     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()) {
280 #ifdef MXCFLASH_SELECT_MMC
281        return mmcflash_read_buf(addr, data, len);
282 #endif
283     } else {
284        return -1;
285     }
286     return 0;
287 }
288
289 int flash_lock_block(void* block)
290 {
291     if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
292 #ifdef MXCFLASH_SELECT_NOR
293         return norflash_lock_block(block);
294 #endif
295     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
296 #ifdef MXCFLASH_SELECT_MMC
297         return mmcflash_lock_block(block);
298 #endif
299     } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
300 #ifdef MXCFLASH_SELECT_NAND
301         return nandflash_lock_block(block);
302 #endif
303     }
304     return 0;
305 }
306
307 int flash_unlock_block(void* block, int block_size, int blocks)
308 {
309     if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
310 #ifdef MXCFLASH_SELECT_NOR
311         return norflash_unlock_block(block, block_size, blocks);
312 #endif
313     } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
314 #ifdef MXCFLASH_SELECT_MMC
315         return mmcflash_unlock_block(block, block_size, blocks);
316 #endif
317     } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
318 #ifdef MXCFLASH_SELECT_NAND
319         return nandflash_unlock_block(block, block_size, blocks);
320 #endif
321     }
322     return 0;
323 }
324
325 static void mxc_flash_print_info(void)
326 {
327     if (IS_BOOTING_FROM_NOR()) {
328         diag_printf("\nBooting from [NOR flash]\n");
329     } else if (IS_BOOTING_FROM_NAND()) {
330 #ifdef MXCFLASH_SELECT_NAND
331         diag_printf("\nBooting from [NAND flash]\n");
332         mxc_nfc_print_info();
333 #endif
334     } else if (IS_BOOTING_FROM_SPI_NOR()) {
335 #ifdef MXCFLASH_SELECT_SPI_NOR
336         diag_printf("\nBooting from [SPI NOR flash]\n");
337         imx_spi_nor_print_info();
338 #endif
339     } else if (IS_BOOTING_FROM_SDRAM()) {
340         diag_printf("\nBooting from [SDRAM]\n");
341     } else if (IS_BOOTING_FROM_MMC() ){
342 #ifdef MXCFLASH_SELECT_MMC
343         mxc_mmc_print_info();
344 #else
345         return;
346 #endif
347     }
348     diag_printf("\n");
349 }
350
351 RedBoot_init(mxc_flash_print_info, RedBoot_INIT_LAST);