Commit f1b6c814f70431be638f99bef8404a51c9a87349
1 parent
55dbdd9d56
Exists in
smarc_8mm-imx_v2018.03_4.14.98_2.0.0_ga
and in
4 other branches
MLK-20962: Support legacy full id NAND in SPL
Current SPL code only support ONFI-compatible NAND, porting the code from nand_base.c to support legacy full id NAND chips, such as Toshiba TC58NVG2S0H. Signed-off-by: Han Xu <han.xu@nxp.com> (cherry picked from commit 4086c6b9556acbec2a8748578eb4a9e719ab4ae7)
Showing 2 changed files with 65 additions and 6 deletions Side-by-side Diff
drivers/mtd/nand/Makefile
... | ... | @@ -72,6 +72,7 @@ |
72 | 72 | obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o |
73 | 73 | obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_spl.o |
74 | 74 | obj-$(CONFIG_NAND_MXC) += mxc_nand_spl.o |
75 | +obj-y += nand_ids.o | |
75 | 76 | obj-$(CONFIG_NAND_MXS) += mxs_nand_spl.o mxs_nand.o |
76 | 77 | obj-$(CONFIG_NAND_SUNXI) += sunxi_nand_spl.o |
77 | 78 |
drivers/mtd/nand/mxs_nand_spl.c
1 | 1 | /* |
2 | 2 | * Copyright (C) 2014 Gateworks Corporation |
3 | + * Copyright 2019 NXP | |
3 | 4 | * Author: Tim Harvey <tharvey@gateworks.com> |
4 | 5 | * |
5 | 6 | * SPDX-License-Identifier: GPL-2.0+ |
... | ... | @@ -7,6 +8,7 @@ |
7 | 8 | #include <common.h> |
8 | 9 | #include <nand.h> |
9 | 10 | #include <malloc.h> |
11 | +#include <linux/mtd/rawnand.h> | |
10 | 12 | |
11 | 13 | static struct mtd_info *mtd; |
12 | 14 | static struct nand_chip nand_chip; |
13 | 15 | |
14 | 16 | |
15 | 17 | |
... | ... | @@ -140,14 +142,55 @@ |
140 | 142 | return ret; |
141 | 143 | } |
142 | 144 | |
145 | +/* Extract the bits of per cell from the 3rd byte of the extended ID */ | |
146 | +static int nand_get_bits_per_cell(u8 cellinfo) | |
147 | +{ | |
148 | + int bits; | |
143 | 149 | |
144 | -static int mxs_flash_ident(struct mtd_info *mtd) | |
150 | + bits = cellinfo & NAND_CI_CELLTYPE_MSK; | |
151 | + bits >>= NAND_CI_CELLTYPE_SHIFT; | |
152 | + return bits + 1; | |
153 | +} | |
154 | + | |
155 | +static inline bool is_full_id_nand(struct nand_flash_dev *type) | |
145 | 156 | { |
157 | + return type->id_len; | |
158 | +} | |
159 | + | |
160 | +static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, | |
161 | + struct nand_flash_dev *type, u8 *id_data, int *busw) | |
162 | +{ | |
163 | + if (!strncmp((char *)type->id, (char *)id_data, type->id_len)) { | |
164 | + mtd->writesize = type->pagesize; | |
165 | + mtd->erasesize = type->erasesize; | |
166 | + mtd->oobsize = type->oobsize; | |
167 | + | |
168 | + chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); | |
169 | + chip->chipsize = (uint64_t)type->chipsize << 20; | |
170 | + chip->options |= type->options; | |
171 | + chip->ecc_strength_ds = NAND_ECC_STRENGTH(type); | |
172 | + chip->ecc_step_ds = NAND_ECC_STEP(type); | |
173 | + chip->onfi_timing_mode_default = | |
174 | + type->onfi_timing_mode_default; | |
175 | + | |
176 | + *busw = type->options & NAND_BUSWIDTH_16; | |
177 | + | |
178 | + if (!mtd->name) | |
179 | + mtd->name = type->name; | |
180 | + | |
181 | + return true; | |
182 | + } | |
183 | + return false; | |
184 | +} | |
185 | + | |
186 | +static int mxs_flash_ident(struct mtd_info *mtd, struct nand_flash_dev *type) | |
187 | +{ | |
146 | 188 | register struct nand_chip *chip = mtd_to_nand(mtd); |
147 | 189 | int i, val; |
148 | 190 | u8 mfg_id, dev_id; |
149 | 191 | u8 id_data[8]; |
150 | 192 | struct nand_onfi_params *p = &chip->onfi_params; |
193 | + int busw = 0; | |
151 | 194 | |
152 | 195 | /* Reset the chip */ |
153 | 196 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); |
... | ... | @@ -169,6 +212,18 @@ |
169 | 212 | } |
170 | 213 | debug("0x%02x:0x%02x ", mfg_id, dev_id); |
171 | 214 | |
215 | + if (!type) | |
216 | + type = nand_flash_ids; | |
217 | + | |
218 | + for (; type->name != NULL; type++) { | |
219 | + if (is_full_id_nand(type)) { | |
220 | + if (find_full_id_nand(mtd, chip, type, id_data, &busw)) | |
221 | + goto ident_done; | |
222 | + } else if (dev_id == type->dev_id) { | |
223 | + break; | |
224 | + } | |
225 | + } | |
226 | + | |
172 | 227 | /* read ONFI */ |
173 | 228 | chip->onfi_version = 0; |
174 | 229 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); |
175 | 230 | |
176 | 231 | |
... | ... | @@ -223,11 +278,14 @@ |
223 | 278 | printf("Could not retrieve ONFI ECC requirements\n"); |
224 | 279 | } |
225 | 280 | |
281 | +ident_done: | |
282 | + chip->page_shift = ffs(mtd->writesize) - 1; | |
283 | + chip->phys_erase_shift = ffs(mtd->erasesize) - 1; | |
226 | 284 | debug("ecc_strength_ds %u, ecc_step_ds %u\n", chip->ecc_strength_ds, chip->ecc_step_ds); |
227 | - debug("erasesize=%d (>>%d)\n", mtd->erasesize, chip->phys_erase_shift); | |
228 | - debug("writesize=%d (>>%d)\n", mtd->writesize, chip->page_shift); | |
285 | + debug("erasesize=%x (>>%d)\n", mtd->erasesize, chip->phys_erase_shift); | |
286 | + debug("writesize=%x (>>%d)\n", mtd->writesize, chip->page_shift); | |
229 | 287 | debug("oobsize=%d\n", mtd->oobsize); |
230 | - debug("chipsize=%lld\n", chip->chipsize); | |
288 | + debug("chipsize=%llx\n", chip->chipsize); | |
231 | 289 | |
232 | 290 | return 0; |
233 | 291 | } |
... | ... | @@ -276,7 +334,7 @@ |
276 | 334 | nand_chip.numchips = 1; |
277 | 335 | |
278 | 336 | /* identify flash device */ |
279 | - if (mxs_flash_ident(mtd)) { | |
337 | + if (mxs_flash_ident(mtd, NULL)) { | |
280 | 338 | printf("Failed to identify\n"); |
281 | 339 | return -1; |
282 | 340 | } |
... | ... | @@ -314,7 +372,7 @@ |
314 | 372 | page_off = offs & (mtd->writesize - 1); |
315 | 373 | nand_page_per_block = mtd->erasesize / mtd->writesize; |
316 | 374 | |
317 | - debug("%s offset:0x%08x len:%d page:%d\n", __func__, offs, size, page); | |
375 | + debug("%s offset:0x%08x len:%d page:%x\n", __func__, offs, size, page); | |
318 | 376 | |
319 | 377 | while (size) { |
320 | 378 | if (mxs_read_page_ecc(mtd, page_buf, page) < 0) |