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