18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2017 Free Electrons
48c2ecf20Sopenharmony_ci * Copyright (C) 2017 NextThing Co
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "internals.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistatic void amd_nand_decode_id(struct nand_chip *chip)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	struct mtd_info *mtd = nand_to_mtd(chip);
148c2ecf20Sopenharmony_ci	struct nand_memory_organization *memorg;
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	memorg = nanddev_get_memorg(&chip->base);
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	nand_decode_ext_id(chip);
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	/*
218c2ecf20Sopenharmony_ci	 * Check for Spansion/AMD ID + repeating 5th, 6th byte since
228c2ecf20Sopenharmony_ci	 * some Spansion chips have erasesize that conflicts with size
238c2ecf20Sopenharmony_ci	 * listed in nand_ids table.
248c2ecf20Sopenharmony_ci	 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
258c2ecf20Sopenharmony_ci	 */
268c2ecf20Sopenharmony_ci	if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 &&
278c2ecf20Sopenharmony_ci	    chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 &&
288c2ecf20Sopenharmony_ci	    memorg->pagesize == 512) {
298c2ecf20Sopenharmony_ci		memorg->pages_per_eraseblock = 256;
308c2ecf20Sopenharmony_ci		memorg->pages_per_eraseblock <<= ((chip->id.data[3] & 0x03) << 1);
318c2ecf20Sopenharmony_ci		mtd->erasesize = memorg->pages_per_eraseblock *
328c2ecf20Sopenharmony_ci				 memorg->pagesize;
338c2ecf20Sopenharmony_ci	}
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistatic int amd_nand_init(struct nand_chip *chip)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	if (nand_is_slc(chip))
398c2ecf20Sopenharmony_ci		/*
408c2ecf20Sopenharmony_ci		 * According to the datasheet of some Cypress SLC NANDs,
418c2ecf20Sopenharmony_ci		 * the bad block markers can be in the first, second or last
428c2ecf20Sopenharmony_ci		 * page of a block. So let's check all three locations.
438c2ecf20Sopenharmony_ci		 */
448c2ecf20Sopenharmony_ci		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
458c2ecf20Sopenharmony_ci				 NAND_BBM_LASTPAGE;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	return 0;
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciconst struct nand_manufacturer_ops amd_nand_manuf_ops = {
518c2ecf20Sopenharmony_ci	.detect = amd_nand_decode_id,
528c2ecf20Sopenharmony_ci	.init = amd_nand_init,
538c2ecf20Sopenharmony_ci};
54