00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <linux/types.h>
00037 #include <linux/autoconf.h>
00038
00039 #include "mtd.h"
00040 #include "nand.h"
00041 #include "delay.h"
00042
00043 #include <asm/arch/hwregs/reg_rdwr.h>
00044 #include <asm/arch/hwregs/reg_map.h>
00045 #include <asm/arch/hwregs/pinmux_defs.h>
00046
00047 #include <asm/arch/hwregs/reg_map.h>
00048 #include <asm/arch/hwregs/bif_core_defs.h>
00049 #include <asm/arch/hwregs/gio_defs.h>
00050 #include <asm/arch/hwregs/pinmux_defs.h>
00051
00052 #include "lib.h"
00053
00054 #include "bootconfig.h"
00055
00056 #define BOOTDEBUG 1
00057 #define MORE_BOOTDEBUG 1
00058
00059
00060
00061
00062 #define NANDRW_READ 0x01
00063 #define NANDRW_WRITE 0x00
00064 #define NANDRW_JFFS2 0x02
00065 #define NANDRW_JFFS2_SKIP 0x04
00066
00067 #define ROUND_DOWN(value, boundary) ((value) & (~((boundary)-1)))
00068
00069
00070
00071 #define SET_MAGIC_AND_BOOT(ADDR, MAGIC_R8, MAGIC_R12) \
00072 __asm__ volatile (" \
00073 move.d " #MAGIC_R8 ", $r8\n\
00074 move.d " #MAGIC_R12 ", $r12\n\
00075 jump %0\n\
00076 nop\n\
00077 " : : "r" (ADDR))
00078 #define BOOT1(ADDR, MAGIC_R8, MAGIC_R12) \
00079 SET_MAGIC_AND_BOOT(ADDR, MAGIC_R8, MAGIC_R12);
00080 #define BOOT(ADDR) \
00081 BOOT1(ADDR, RAM_INIT_MAGIC, NAND_BOOT_MAGIC);
00082
00083 extern struct mtd_info *crisv32_nand_flash_probe(void);
00084
00085 extern int _end, _bss, _edata;
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 static int
00099 nand_rw (struct mtd_info* mtd, int cmd,
00100 size_t start, size_t len,
00101 size_t *retlen, u_char * buf)
00102 {
00103 int total = 0;
00104 int ret = 0;
00105 int n;
00106
00107
00108
00109
00110 size_t eblk = ~0;
00111 size_t erasesize = mtd->erasesize;
00112
00113 putnl();
00114 while (len) {
00115 if ((start & (-erasesize)) != eblk) {
00116
00117
00118
00119 eblk = start & (-erasesize);
00120 #if BOOTDEBUG
00121 puts("New block ");
00122 putx(eblk);
00123 puts(";len: ");
00124 putx(len);
00125 puts(";start: ");
00126 putx(start);
00127 putnl();
00128 #endif
00129
00130 if (mtd->block_isbad(mtd, eblk)) {
00131 if (cmd == (NANDRW_READ | NANDRW_JFFS2)) {
00132
00133 start += erasesize;
00134 puts("bad block - skip it ...1");
00135 putnl();
00136
00137
00138
00139
00140
00141
00142
00143
00144 continue;
00145 } else if (cmd == (NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP)) {
00146 puts("bad block - skip it ...2");
00147 putnl();
00148 start += erasesize;
00149 continue;
00150 } else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) {
00151 puts("bad block - skip it ...3");
00152 putnl();
00153
00154 start += erasesize;
00155 continue;
00156 } else {
00157 puts("bad block - skip it ...4");
00158 putnl();
00159 ret = 1;
00160 break;
00161 }
00162 }
00163 }
00164
00165 #if 0
00166 buf = (void *) 0x38008000;
00167 #endif
00168
00169 if (cmd & NANDRW_READ) {
00170 ret = mtd->read_ecc(mtd, start,
00171 min(len, eblk + erasesize - start),
00172 (size_t *)&n, (u_char*)buf,
00173 NULL, NULL);
00174 } else {
00175 ret = mtd->write_ecc(mtd, start,
00176 min(len, eblk + erasesize - start),
00177 (size_t *)&n, (u_char*)buf,
00178 NULL, NULL);
00179 }
00180
00181 if (ret) {
00182 break;
00183 }
00184
00185 start += n;
00186 buf += n;
00187 total += n;
00188 len -= n;
00189 }
00190 if (retlen)
00191 *retlen = total;
00192
00193 return ret;
00194 }
00195
00196
00197 void
00198 bootload(void)
00199 {
00200 char revision;
00201 struct mtd_info *mtd;
00202 int res;
00203 int copied;
00204 #if BOOTDEBUG
00205 int i;
00206 #endif
00207
00208 serial_init();
00209
00210
00211
00212 *(unsigned long *)REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg) = CONFIG_ETRAX_MEM_GRP3_CONFIG;
00213
00214
00215 __asm__ volatile ("move $vr,%0" : "=rm" (revision));
00216 if (revision < 32) {
00217 error("You need an ETRAX FS to run Linux 2.6/crisv32.\r\n");
00218 while(1);
00219 }
00220 puts("Clear cmdline from memory") ;
00221 putnl();
00222 unsigned long *ul_cmdline_ram = (unsigned long *)0xC0004000;
00223 ul_cmdline_ram[0] = 0x00000000;
00224
00225 #if BOOTDEBUG
00226 puts("\r\n\nETRAX FS NAND boot loader\r\n");
00227 puts("=========================\r\n");
00228 puts("Rev 1, " __DATE__ " " __TIME__ "\r\n");
00229
00230 puts("Boot config: ");
00231 putx(FETCH_ADDR);
00232 puts("->");
00233 putx(STORE_ADDR);
00234 puts(", len ");
00235 putx(LOAD_SIZE);
00236 puts(", boot @ ");
00237 putx(BOOT_ADDR);
00238 putnl();
00239
00240 puts("CPU revision: ");
00241 putx(revision);
00242 putnl();
00243
00244 #if MORE_BOOTDEBUG
00245 puts("Bootloader main at ") ;
00246 putx((int) bootload);
00247 putnl();
00248
00249 puts("Data end: ");
00250 putx((long) &_edata);
00251 putnl();
00252
00253 puts("Bss: ");
00254 putx((long) &_bss);
00255 putnl();
00256
00257 puts("Heap: ");
00258 putx((long) &_end);
00259 putnl();
00260 #endif
00261
00262 puts("Identifying nand chip...\r\n");
00263 #endif
00264
00265 mtd = crisv32_nand_flash_probe();
00266
00267 #if BOOTDEBUG
00268 puts("Done.\r\n");
00269 #endif
00270
00271 if (!mtd)
00272 error("No NAND flash chip found to boot from.");
00273
00274 #if BOOTDEBUG
00275 puts("Chip identified... 3; ");
00276
00277 #if MORE_BOOTDEBUG
00278 if (mtd->name)
00279 puts(mtd->name);
00280
00281 puts("\r\ntype: ");
00282 putx(mtd->type);
00283 puts("\r\nflags: ");
00284 putx(mtd->flags);
00285 puts("\r\nsize: ");
00286 putx(mtd->size);
00287 puts("\r\nerasesize: ");
00288 putx(mtd->erasesize);
00289 puts("\r\noobblock: ");
00290 putx(mtd->oobblock);
00291 puts("\r\noobsize: ");
00292 putx(mtd->oobsize);
00293 puts("\r\necctype: ");
00294 putx(mtd->ecctype);
00295 puts("\r\neccsize: ");
00296 putx(mtd->eccsize);
00297 #endif
00298 putnl();
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 #endif
00311
00312 #if MORE_BOOTDEBUG
00313 puts("Oob info:\r\n");
00314 puts("useecc: ");
00315 putx(mtd->oobinfo.useecc);
00316 puts("\r\neccbytes: ");
00317 putx(mtd->oobinfo.eccbytes);
00318 puts("\r\neccpos: ");
00319 for (i = 0; i < mtd->oobinfo.eccbytes; i++) {
00320 putx(mtd->oobinfo.eccpos[i]);
00321 putc(' ');
00322 }
00323 putnl();
00324 #endif
00325
00326 #if BOOTDEBUG
00327 puts("Bootload in progress...");
00328 #endif
00329
00330
00331
00332
00333
00334 res = nand_rw(mtd,
00335 NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP,
00336 FETCH_ADDR, LOAD_SIZE, &copied,
00337 (void *) STORE_ADDR);
00338
00339
00340 #if BOOTDEBUG
00341 puts("complete, status ");
00342 putx(res);
00343 puts(", loaded ");
00344 putx(copied);
00345 puts(" bytes\r\n");
00346
00347 puts("Data in DRAM:\r\n");
00348 putx(* (int *) STORE_ADDR);
00349 putc(' ');
00350 putx(* (int *) (STORE_ADDR+4));
00351 putc(' ');
00352 putx(* (int *) (STORE_ADDR+8));
00353 putnl();
00354 #endif
00355
00356 if (res)
00357 error("Corrupt data in NAND flash.");
00358
00359 #if BOOTDEBUG
00360 puts("Booting...\r\n");
00361 #endif
00362
00363 BOOT(BOOT_ADDR);
00364
00365 while (1)
00366 ;
00367 }