1 /* 2 * NAND boot for Freescale Enhanced Local Bus Controller, Flash Control Machine 3 * 4 * (C) Copyright 2006-2008 5 * Stefan Roese, DENX Software Engineering, sr@denx.de. 6 * 7 * Copyright (c) 2008 Freescale Semiconductor, Inc. 8 * Author: Scott Wood <scottwood@freescale.com> 9 * 10 * SPDX-License-Identifier: GPL-2.0+ 11 */ 12 13 #include <common.h> 14 #include <asm/io.h> 15 #include <asm/fsl_lbc.h> 16 #include <nand.h> 17 18 #define WINDOW_SIZE 8192 19 20 static void nand_wait(void) 21 { 22 fsl_lbc_t *regs = LBC_BASE_ADDR; 23 24 for (;;) { 25 uint32_t status = in_be32(®s->ltesr); 26 27 if (status == 1) 28 return; 29 30 if (status & 1) { 31 puts("read failed (ltesr)\n"); 32 for (;;); 33 } 34 } 35 } 36 37 #ifdef CONFIG_TPL_BUILD 38 int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst) 39 #else 40 static int nand_load_image(uint32_t offs, unsigned int uboot_size, void *vdst) 41 #endif 42 { 43 fsl_lbc_t *regs = LBC_BASE_ADDR; 44 uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE; 45 const int large = CONFIG_SYS_NAND_OR_PRELIM & OR_FCM_PGS; 46 const int block_shift = large ? 17 : 14; 47 const int block_size = 1 << block_shift; 48 const int page_size = large ? 2048 : 512; 49 const int bad_marker = large ? page_size + 0 : page_size + 5; 50 int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2; 51 int pos = 0; 52 char *dst = vdst; 53 54 if (offs & (block_size - 1)) { 55 puts("bad offset\n"); 56 for (;;); 57 } 58 59 if (large) { 60 fmr |= FMR_ECCM; 61 out_be32(®s->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | 62 (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); 63 out_be32(®s->fir, 64 (FIR_OP_CW0 << FIR_OP0_SHIFT) | 65 (FIR_OP_CA << FIR_OP1_SHIFT) | 66 (FIR_OP_PA << FIR_OP2_SHIFT) | 67 (FIR_OP_CW1 << FIR_OP3_SHIFT) | 68 (FIR_OP_RBW << FIR_OP4_SHIFT)); 69 } else { 70 out_be32(®s->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT); 71 out_be32(®s->fir, 72 (FIR_OP_CW0 << FIR_OP0_SHIFT) | 73 (FIR_OP_CA << FIR_OP1_SHIFT) | 74 (FIR_OP_PA << FIR_OP2_SHIFT) | 75 (FIR_OP_RBW << FIR_OP3_SHIFT)); 76 } 77 78 out_be32(®s->fbcr, 0); 79 clrsetbits_be32(®s->bank[0].br, BR_DECC, BR_DECC_CHK_GEN); 80 81 while (pos < uboot_size) { 82 int i = 0; 83 out_be32(®s->fbar, offs >> block_shift); 84 85 do { 86 int j; 87 unsigned int page_offs = (offs & (block_size - 1)) << 1; 88 89 out_be32(®s->ltesr, ~0); 90 out_be32(®s->lteatr, 0); 91 out_be32(®s->fpar, page_offs); 92 out_be32(®s->fmr, fmr); 93 out_be32(®s->lsor, 0); 94 nand_wait(); 95 96 page_offs %= WINDOW_SIZE; 97 98 /* 99 * If either of the first two pages are marked bad, 100 * continue to the next block. 101 */ 102 if (i++ < 2 && buf[page_offs + bad_marker] != 0xff) { 103 puts("skipping\n"); 104 offs = (offs + block_size) & ~(block_size - 1); 105 pos &= ~(block_size - 1); 106 break; 107 } 108 109 for (j = 0; j < page_size; j++) 110 dst[pos + j] = buf[page_offs + j]; 111 112 pos += page_size; 113 offs += page_size; 114 } while ((offs & (block_size - 1)) && (pos < uboot_size)); 115 } 116 117 return 0; 118 } 119 120 /* 121 * Defines a static function nand_load_image() here, because non-static makes 122 * the code too large for certain SPLs(minimal SPL, maximum size <= 4Kbytes) 123 */ 124 #ifndef CONFIG_TPL_BUILD 125 #define nand_spl_load_image(offs, uboot_size, vdst) \ 126 nand_load_image(offs, uboot_size, vdst) 127 #endif 128 129 /* 130 * The main entry for NAND booting. It's necessary that SDRAM is already 131 * configured and available since this code loads the main U-Boot image 132 * from NAND into SDRAM and starts it from there. 133 */ 134 void nand_boot(void) 135 { 136 __attribute__((noreturn)) void (*uboot)(void); 137 /* 138 * Load U-Boot image from NAND into RAM 139 */ 140 nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, 141 CONFIG_SYS_NAND_U_BOOT_SIZE, 142 (void *)CONFIG_SYS_NAND_U_BOOT_DST); 143 144 #ifdef CONFIG_NAND_ENV_DST 145 nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, 146 (void *)CONFIG_NAND_ENV_DST); 147 148 #ifdef CONFIG_ENV_OFFSET_REDUND 149 nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE, 150 (void *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE); 151 #endif 152 #endif 153 154 #ifdef CONFIG_SPL_FLUSH_IMAGE 155 /* 156 * Clean d-cache and invalidate i-cache, to 157 * make sure that no stale data is executed. 158 */ 159 flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE); 160 #endif 161 162 puts("transfering control\n"); 163 /* 164 * Jump to U-Boot image 165 */ 166 uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START; 167 (*uboot)(); 168 } 169