Blame view
nand_spl/nand_boot_fsl_elbc.c
3.37 KB
e4c095085 NAND boot: MPC831... |
1 2 3 4 5 6 7 8 9 |
/* * NAND boot for Freescale Enhanced Local Bus Controller, Flash Control Machine * * (C) Copyright 2006-2008 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * Copyright (c) 2008 Freescale Semiconductor, Inc. * Author: Scott Wood <scottwood@freescale.com> * |
1a4596601 Add GPL-2.0+ SPDX... |
10 |
* SPDX-License-Identifier: GPL-2.0+ |
e4c095085 NAND boot: MPC831... |
11 12 13 14 |
*/ #include <common.h> #include <asm/io.h> |
e4c095085 NAND boot: MPC831... |
15 16 17 18 19 20 21 |
#include <asm/fsl_lbc.h> #include <linux/mtd/nand.h> #define WINDOW_SIZE 8192 static void nand_wait(void) { |
f51cdaf19 83xx/85xx/86xx: L... |
22 |
fsl_lbc_t *regs = LBC_BASE_ADDR; |
e4c095085 NAND boot: MPC831... |
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
for (;;) { uint32_t status = in_be32(®s->ltesr); if (status == 1) return; if (status & 1) { puts("read failed (ltesr) "); for (;;); } } } static void nand_load(unsigned int offs, int uboot_size, uchar *dst) { |
f51cdaf19 83xx/85xx/86xx: L... |
40 |
fsl_lbc_t *regs = LBC_BASE_ADDR; |
6d0f6bcf3 rename CFG_ macro... |
41 |
uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE; |
629745468 nand/spl: Assumin... |
42 43 44 45 46 |
const int large = CONFIG_SYS_NAND_OR_PRELIM & OR_FCM_PGS; const int block_shift = large ? 17 : 14; const int block_size = 1 << block_shift; const int page_size = large ? 2048 : 512; const int bad_marker = large ? page_size + 0 : page_size + 5; |
e4c095085 NAND boot: MPC831... |
47 48 49 50 51 52 53 54 55 56 57 |
int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2; int pos = 0; if (offs & (block_size - 1)) { puts("bad offset "); for (;;); } if (large) { fmr |= FMR_ECCM; |
7b8f6685f nand/fsl_elbc: sh... |
58 59 60 61 62 63 64 65 66 67 |
__raw_writel((NAND_CMD_READ0 << FCR_CMD0_SHIFT) | (NAND_CMD_READSTART << FCR_CMD1_SHIFT), ®s->fcr); __raw_writel( (FIR_OP_CW0 << FIR_OP0_SHIFT) | (FIR_OP_CA << FIR_OP1_SHIFT) | (FIR_OP_PA << FIR_OP2_SHIFT) | (FIR_OP_CW1 << FIR_OP3_SHIFT) | (FIR_OP_RBW << FIR_OP4_SHIFT), ®s->fir); |
e4c095085 NAND boot: MPC831... |
68 |
} else { |
7b8f6685f nand/fsl_elbc: sh... |
69 70 71 72 73 74 75 |
__raw_writel(NAND_CMD_READ0 << FCR_CMD0_SHIFT, ®s->fcr); __raw_writel( (FIR_OP_CW0 << FIR_OP0_SHIFT) | (FIR_OP_CA << FIR_OP1_SHIFT) | (FIR_OP_PA << FIR_OP2_SHIFT) | (FIR_OP_RBW << FIR_OP3_SHIFT), ®s->fir); |
e4c095085 NAND boot: MPC831... |
76 |
} |
7b8f6685f nand/fsl_elbc: sh... |
77 |
__raw_writel(0, ®s->fbcr); |
e4c095085 NAND boot: MPC831... |
78 79 80 |
while (pos < uboot_size) { int i = 0; |
7b8f6685f nand/fsl_elbc: sh... |
81 |
__raw_writel(offs >> block_shift, ®s->fbar); |
e4c095085 NAND boot: MPC831... |
82 83 84 85 |
do { int j; unsigned int page_offs = (offs & (block_size - 1)) << 1; |
7b8f6685f nand/fsl_elbc: sh... |
86 87 88 89 90 91 |
__raw_writel(~0, ®s->ltesr); __raw_writel(0, ®s->lteatr); __raw_writel(page_offs, ®s->fpar); __raw_writel(fmr, ®s->fmr); sync(); __raw_writel(0, ®s->lsor); |
e4c095085 NAND boot: MPC831... |
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
nand_wait(); page_offs %= WINDOW_SIZE; /* * If either of the first two pages are marked bad, * continue to the next block. */ if (i++ < 2 && buf[page_offs + bad_marker] != 0xff) { puts("skipping "); offs = (offs + block_size) & ~(block_size - 1); pos &= ~(block_size - 1); break; } for (j = 0; j < page_size; j++) dst[pos + j] = buf[page_offs + j]; pos += page_size; offs += page_size; |
269610f6b NAND boot: fix na... |
113 |
} while ((offs & (block_size - 1)) && (pos < uboot_size)); |
e4c095085 NAND boot: MPC831... |
114 115 116 117 118 119 120 121 122 123 124 |
} } /* * The main entry for NAND booting. It's necessary that SDRAM is already * configured and available since this code loads the main U-Boot image * from NAND into SDRAM and starts it from there. */ void nand_boot(void) { __attribute__((noreturn)) void (*uboot)(void); |
e4c095085 NAND boot: MPC831... |
125 126 127 |
/* * Load U-Boot image from NAND into RAM */ |
6d0f6bcf3 rename CFG_ macro... |
128 |
nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE, |
93e145964 Coding Style clea... |
129 |
(uchar *)CONFIG_SYS_NAND_U_BOOT_DST); |
e4c095085 NAND boot: MPC831... |
130 131 132 133 134 135 |
/* * Jump to U-Boot image */ puts("transfering control "); |
c70564e6b NAND: Fix cache a... |
136 137 138 139 140 |
/* * Clean d-cache and invalidate i-cache, to * make sure that no stale data is executed. */ flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE); |
6d0f6bcf3 rename CFG_ macro... |
141 |
uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START; |
e4c095085 NAND boot: MPC831... |
142 143 |
uboot(); } |