1 //==========================================================================
5 // Flash programming wrapper to support both NOR and NAND flashes
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.
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.
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
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.
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.
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.
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####
43 // Author(s): Kevin Zhang <k.zhang@freescale.com>
44 // Contributors: Kevin Zhang <k.zhang@freescale.com>
49 //####DESCRIPTIONEND####
51 //==========================================================================
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>
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);
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);
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);
90 extern void ata_hwr_init(void);
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);
102 #ifndef IS_BOOTING_FROM_SPI_NOR()
103 #define IS_BOOTING_FROM_SPI_NOR() 0
105 #ifndef IS_FIS_FROM_SPI_NOR()
106 #define IS_FIS_FROM_SPI_NOR() 0
109 static int mxc_flash_warning_done = 0;
111 void flash_query(void* data)
113 if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
114 #ifdef MXCFLASH_SELECT_NOR
115 norflash_query(data);
117 } else if (IS_BOOTING_FROM_SPI_NOR() || IS_FIS_FROM_SPI_NOR()){
118 #ifdef IMXFLASH_SELECT_SPI_NOR
119 spi_norflash_query(data);
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);
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");
135 int flash_hwr_init(void)
137 if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
138 #ifdef MXCFLASH_SELECT_NOR
139 return norflash_hwr_init();
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 */
147 return spi_norflash_hwr_init();
149 } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
150 #ifdef MXCFLASH_SELECT_NAND
151 return nandflash_hwr_init();
153 } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
154 #ifdef MXCFLASH_SELECT_MMC
155 return mmcflash_hwr_init();
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");
167 int flash_hwr_map_error(int e)
169 if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
170 #ifdef MXCFLASH_SELECT_NOR
171 return norflash_hwr_map_error(e);
173 } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
174 #ifdef MXCFLASH_SELECT_NAND
175 return nandflash_hwr_map_error(e);
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);
181 } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
182 #ifdef MXCFLASH_SELECT_MMC
183 return mmcflash_hwr_map_error(e);
189 bool flash_code_overlaps(void *start, void *end)
191 if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
192 #ifdef MXCFLASH_SELECT_NOR
193 return norflash_code_overlaps(start, end);
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);
199 } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
200 #ifdef MXCFLASH_SELECT_MMC
201 return mmcflash_code_overlaps(start, end);
203 } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()){
204 #ifdef MXCFLASH_SELECT_NAND
205 return nandflash_code_overlaps(start, end);
208 diag_printf("Error %d: where is fis\n", __LINE__);
214 int flash_erase_block(void* block, unsigned int size)
216 if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
217 #ifdef MXCFLASH_SELECT_NOR
218 return norflash_erase_block(block, size);
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);
224 } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
225 #ifdef MXCFLASH_SELECT_MMC
226 return mmcflash_erase_block(block, size);
228 } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()){
229 #ifdef MXCFLASH_SELECT_NAND
230 return nandflash_erase_block(block, size);
233 diag_printf("Error %d: where is fis\n", __LINE__);
239 int flash_program_buf(void* addr, void* data, int len)
241 if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
242 #ifdef MXCFLASH_SELECT_NOR
243 return norflash_program_buf(addr, data, len);
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);
249 } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
250 #ifdef MXCFLASH_SELECT_NAND
251 return nandflash_program_buf(addr, data, len);
253 } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
254 #ifdef MXCFLASH_SELECT_MMC
255 return mmcflash_program_buf(addr, data, len);
264 int flash_read_buf(void* addr, void* data, int len)
266 if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()){
267 #ifdef MXCFLASH_SELECT_NAND
268 return nandflash_read_buf(addr, data, len);
270 } else if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
271 #ifdef MXCFLASH_SELECT_NOR
272 memcpy(data, addr, len);
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);
279 } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()) {
280 #ifdef MXCFLASH_SELECT_MMC
281 return mmcflash_read_buf(addr, data, len);
289 int flash_lock_block(void* block)
291 if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
292 #ifdef MXCFLASH_SELECT_NOR
293 return norflash_lock_block(block);
295 } else if (IS_BOOTING_FROM_MMC() || IS_FIS_FROM_MMC()){
296 #ifdef MXCFLASH_SELECT_MMC
297 return mmcflash_lock_block(block);
299 } else if (IS_BOOTING_FROM_NAND() || IS_FIS_FROM_NAND()) {
300 #ifdef MXCFLASH_SELECT_NAND
301 return nandflash_lock_block(block);
307 int flash_unlock_block(void* block, int block_size, int blocks)
309 if (IS_BOOTING_FROM_NOR() || IS_FIS_FROM_NOR()) {
310 #ifdef MXCFLASH_SELECT_NOR
311 return norflash_unlock_block(block, block_size, blocks);
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);
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);
325 static void mxc_flash_print_info(void)
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();
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();
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();
351 RedBoot_init(mxc_flash_print_info, RedBoot_INIT_LAST);