xref: /openbmc/linux/drivers/mtd/nand/raw/nand_amd.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
293db446aSBoris Brezillon /*
393db446aSBoris Brezillon  * Copyright (C) 2017 Free Electrons
493db446aSBoris Brezillon  * Copyright (C) 2017 NextThing Co
593db446aSBoris Brezillon  *
693db446aSBoris Brezillon  * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
793db446aSBoris Brezillon  */
893db446aSBoris Brezillon 
9348d56a8SBoris Brezillon #include "internals.h"
1093db446aSBoris Brezillon 
amd_nand_decode_id(struct nand_chip * chip)1193db446aSBoris Brezillon static void amd_nand_decode_id(struct nand_chip *chip)
1293db446aSBoris Brezillon {
1393db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
14629a442cSBoris Brezillon 	struct nand_memory_organization *memorg;
15629a442cSBoris Brezillon 
16629a442cSBoris Brezillon 	memorg = nanddev_get_memorg(&chip->base);
1793db446aSBoris Brezillon 
1893db446aSBoris Brezillon 	nand_decode_ext_id(chip);
1993db446aSBoris Brezillon 
2093db446aSBoris Brezillon 	/*
2193db446aSBoris Brezillon 	 * Check for Spansion/AMD ID + repeating 5th, 6th byte since
2293db446aSBoris Brezillon 	 * some Spansion chips have erasesize that conflicts with size
2393db446aSBoris Brezillon 	 * listed in nand_ids table.
2493db446aSBoris Brezillon 	 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
2593db446aSBoris Brezillon 	 */
2693db446aSBoris Brezillon 	if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 &&
2793db446aSBoris Brezillon 	    chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 &&
28629a442cSBoris Brezillon 	    memorg->pagesize == 512) {
29629a442cSBoris Brezillon 		memorg->pages_per_eraseblock = 256;
30629a442cSBoris Brezillon 		memorg->pages_per_eraseblock <<= ((chip->id.data[3] & 0x03) << 1);
31629a442cSBoris Brezillon 		mtd->erasesize = memorg->pages_per_eraseblock *
32629a442cSBoris Brezillon 				 memorg->pagesize;
3393db446aSBoris Brezillon 	}
3493db446aSBoris Brezillon }
3593db446aSBoris Brezillon 
amd_nand_init(struct nand_chip * chip)3693db446aSBoris Brezillon static int amd_nand_init(struct nand_chip *chip)
3793db446aSBoris Brezillon {
3893db446aSBoris Brezillon 	if (nand_is_slc(chip))
39598dce70SFrieder Schrempf 		/*
40598dce70SFrieder Schrempf 		 * According to the datasheet of some Cypress SLC NANDs,
41598dce70SFrieder Schrempf 		 * the bad block markers can be in the first, second or last
42598dce70SFrieder Schrempf 		 * page of a block. So let's check all three locations.
43598dce70SFrieder Schrempf 		 */
44598dce70SFrieder Schrempf 		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
45598dce70SFrieder Schrempf 				 NAND_BBM_LASTPAGE;
4693db446aSBoris Brezillon 
4793db446aSBoris Brezillon 	return 0;
4893db446aSBoris Brezillon }
4993db446aSBoris Brezillon 
5093db446aSBoris Brezillon const struct nand_manufacturer_ops amd_nand_manuf_ops = {
5193db446aSBoris Brezillon 	.detect = amd_nand_decode_id,
5293db446aSBoris Brezillon 	.init = amd_nand_init,
5393db446aSBoris Brezillon };
54