1 /* 2 * (C) Copyright 2006-2008 3 * Stefan Roese, DENX Software Engineering, sr@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <nand.h> 10 #include <asm/io.h> 11 #include <linux/mtd/nand_ecc.h> 12 13 static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS; 14 static struct mtd_info *mtd; 15 static struct nand_chip nand_chip; 16 17 #define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / \ 18 CONFIG_SYS_NAND_ECCSIZE) 19 #define ECCTOTAL (ECCSTEPS * CONFIG_SYS_NAND_ECCBYTES) 20 21 22 #if (CONFIG_SYS_NAND_PAGE_SIZE <= 512) 23 /* 24 * NAND command for small page NAND devices (512) 25 */ 26 static int nand_command(int block, int page, uint32_t offs, 27 u8 cmd) 28 { 29 struct nand_chip *this = mtd_to_nand(mtd); 30 int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; 31 32 while (!this->dev_ready(mtd)) 33 ; 34 35 /* Begin command latch cycle */ 36 this->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE); 37 /* Set ALE and clear CLE to start address cycle */ 38 /* Column address */ 39 this->cmd_ctrl(mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE); 40 this->cmd_ctrl(mtd, page_addr & 0xff, NAND_CTRL_ALE); /* A[16:9] */ 41 this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff, 42 NAND_CTRL_ALE); /* A[24:17] */ 43 #ifdef CONFIG_SYS_NAND_4_ADDR_CYCLE 44 /* One more address cycle for devices > 32MiB */ 45 this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f, 46 NAND_CTRL_ALE); /* A[28:25] */ 47 #endif 48 /* Latch in address */ 49 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); 50 51 /* 52 * Wait a while for the data to be ready 53 */ 54 while (!this->dev_ready(mtd)) 55 ; 56 57 return 0; 58 } 59 #else 60 /* 61 * NAND command for large page NAND devices (2k) 62 */ 63 static int nand_command(int block, int page, uint32_t offs, 64 u8 cmd) 65 { 66 struct nand_chip *this = mtd_to_nand(mtd); 67 int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; 68 void (*hwctrl)(struct mtd_info *mtd, int cmd, 69 unsigned int ctrl) = this->cmd_ctrl; 70 71 while (!this->dev_ready(mtd)) 72 ; 73 74 /* Emulate NAND_CMD_READOOB */ 75 if (cmd == NAND_CMD_READOOB) { 76 offs += CONFIG_SYS_NAND_PAGE_SIZE; 77 cmd = NAND_CMD_READ0; 78 } 79 80 /* Shift the offset from byte addressing to word addressing. */ 81 if ((this->options & NAND_BUSWIDTH_16) && !nand_opcode_8bits(cmd)) 82 offs >>= 1; 83 84 /* Begin command latch cycle */ 85 hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE); 86 /* Set ALE and clear CLE to start address cycle */ 87 /* Column address */ 88 hwctrl(mtd, offs & 0xff, 89 NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */ 90 hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */ 91 /* Row address */ 92 hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */ 93 hwctrl(mtd, ((page_addr >> 8) & 0xff), 94 NAND_CTRL_ALE); /* A[27:20] */ 95 #ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE 96 /* One more address cycle for devices > 128MiB */ 97 hwctrl(mtd, (page_addr >> 16) & 0x0f, 98 NAND_CTRL_ALE); /* A[31:28] */ 99 #endif 100 /* Latch in address */ 101 hwctrl(mtd, NAND_CMD_READSTART, 102 NAND_CTRL_CLE | NAND_CTRL_CHANGE); 103 hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); 104 105 /* 106 * Wait a while for the data to be ready 107 */ 108 while (!this->dev_ready(mtd)) 109 ; 110 111 return 0; 112 } 113 #endif 114 115 static int nand_is_bad_block(int block) 116 { 117 struct nand_chip *this = mtd_to_nand(mtd); 118 u_char bb_data[2]; 119 120 nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS, 121 NAND_CMD_READOOB); 122 123 /* 124 * Read one byte (or two if it's a 16 bit chip). 125 */ 126 if (this->options & NAND_BUSWIDTH_16) { 127 this->read_buf(mtd, bb_data, 2); 128 if (bb_data[0] != 0xff || bb_data[1] != 0xff) 129 return 1; 130 } else { 131 this->read_buf(mtd, bb_data, 1); 132 if (bb_data[0] != 0xff) 133 return 1; 134 } 135 136 return 0; 137 } 138 139 #if defined(CONFIG_SYS_NAND_HW_ECC_OOBFIRST) 140 static int nand_read_page(int block, int page, uchar *dst) 141 { 142 struct nand_chip *this = mtd_to_nand(mtd); 143 u_char ecc_calc[ECCTOTAL]; 144 u_char ecc_code[ECCTOTAL]; 145 u_char oob_data[CONFIG_SYS_NAND_OOBSIZE]; 146 int i; 147 int eccsize = CONFIG_SYS_NAND_ECCSIZE; 148 int eccbytes = CONFIG_SYS_NAND_ECCBYTES; 149 int eccsteps = ECCSTEPS; 150 uint8_t *p = dst; 151 152 nand_command(block, page, 0, NAND_CMD_READOOB); 153 this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE); 154 nand_command(block, page, 0, NAND_CMD_READ0); 155 156 /* Pick the ECC bytes out of the oob data */ 157 for (i = 0; i < ECCTOTAL; i++) 158 ecc_code[i] = oob_data[nand_ecc_pos[i]]; 159 160 161 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { 162 this->ecc.hwctl(mtd, NAND_ECC_READ); 163 this->read_buf(mtd, p, eccsize); 164 this->ecc.calculate(mtd, p, &ecc_calc[i]); 165 this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); 166 } 167 168 return 0; 169 } 170 #else 171 static int nand_read_page(int block, int page, void *dst) 172 { 173 struct nand_chip *this = mtd_to_nand(mtd); 174 u_char ecc_calc[ECCTOTAL]; 175 u_char ecc_code[ECCTOTAL]; 176 u_char oob_data[CONFIG_SYS_NAND_OOBSIZE]; 177 int i; 178 int eccsize = CONFIG_SYS_NAND_ECCSIZE; 179 int eccbytes = CONFIG_SYS_NAND_ECCBYTES; 180 int eccsteps = ECCSTEPS; 181 uint8_t *p = dst; 182 183 nand_command(block, page, 0, NAND_CMD_READ0); 184 185 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { 186 if (this->ecc.mode != NAND_ECC_SOFT) 187 this->ecc.hwctl(mtd, NAND_ECC_READ); 188 this->read_buf(mtd, p, eccsize); 189 this->ecc.calculate(mtd, p, &ecc_calc[i]); 190 } 191 this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE); 192 193 /* Pick the ECC bytes out of the oob data */ 194 for (i = 0; i < ECCTOTAL; i++) 195 ecc_code[i] = oob_data[nand_ecc_pos[i]]; 196 197 eccsteps = ECCSTEPS; 198 p = dst; 199 200 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { 201 /* No chance to do something with the possible error message 202 * from correct_data(). We just hope that all possible errors 203 * are corrected by this routine. 204 */ 205 this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); 206 } 207 208 return 0; 209 } 210 #endif 211 212 /* nand_init() - initialize data to make nand usable by SPL */ 213 void nand_init(void) 214 { 215 /* 216 * Init board specific nand support 217 */ 218 mtd = nand_to_mtd(&nand_chip); 219 nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W = 220 (void __iomem *)CONFIG_SYS_NAND_BASE; 221 board_nand_init(&nand_chip); 222 223 #ifdef CONFIG_SPL_NAND_SOFTECC 224 if (nand_chip.ecc.mode == NAND_ECC_SOFT) { 225 nand_chip.ecc.calculate = nand_calculate_ecc; 226 nand_chip.ecc.correct = nand_correct_data; 227 } 228 #endif 229 230 if (nand_chip.select_chip) 231 nand_chip.select_chip(mtd, 0); 232 } 233 234 /* Unselect after operation */ 235 void nand_deselect(void) 236 { 237 if (nand_chip.select_chip) 238 nand_chip.select_chip(mtd, -1); 239 } 240 241 #include "nand_spl_loaders.c" 242