xref: /linux/drivers/mtd/nand/raw/nand_esmt.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
1a68642adSMarcel Ziswiler // SPDX-License-Identifier: GPL-2.0
2a68642adSMarcel Ziswiler /*
3a68642adSMarcel Ziswiler  * Copyright (C) 2018 Toradex AG
4a68642adSMarcel Ziswiler  *
5a68642adSMarcel Ziswiler  * Author: Marcel Ziswiler <marcel.ziswiler@toradex.com>
6a68642adSMarcel Ziswiler  */
7a68642adSMarcel Ziswiler 
8a68642adSMarcel Ziswiler #include <linux/mtd/rawnand.h>
9a68642adSMarcel Ziswiler #include "internals.h"
10a68642adSMarcel Ziswiler 
11a68642adSMarcel Ziswiler static void esmt_nand_decode_id(struct nand_chip *chip)
12a68642adSMarcel Ziswiler {
13*53576c7bSMiquel Raynal 	struct nand_device *base = &chip->base;
14*53576c7bSMiquel Raynal 	struct nand_ecc_props requirements = {};
15*53576c7bSMiquel Raynal 
16a68642adSMarcel Ziswiler 	nand_decode_ext_id(chip);
17a68642adSMarcel Ziswiler 
18a68642adSMarcel Ziswiler 	/* Extract ECC requirements from 5th id byte. */
19a68642adSMarcel Ziswiler 	if (chip->id.len >= 5 && nand_is_slc(chip)) {
20*53576c7bSMiquel Raynal 		requirements.step_size = 512;
21a68642adSMarcel Ziswiler 		switch (chip->id.data[4] & 0x3) {
22a68642adSMarcel Ziswiler 		case 0x0:
23*53576c7bSMiquel Raynal 			requirements.strength = 4;
24a68642adSMarcel Ziswiler 			break;
25a68642adSMarcel Ziswiler 		case 0x1:
26*53576c7bSMiquel Raynal 			requirements.strength = 2;
27a68642adSMarcel Ziswiler 			break;
28a68642adSMarcel Ziswiler 		case 0x2:
29*53576c7bSMiquel Raynal 			requirements.strength = 1;
30a68642adSMarcel Ziswiler 			break;
31a68642adSMarcel Ziswiler 		default:
32a68642adSMarcel Ziswiler 			WARN(1, "Could not get ECC info");
33*53576c7bSMiquel Raynal 			requirements.step_size = 0;
34a68642adSMarcel Ziswiler 			break;
35a68642adSMarcel Ziswiler 		}
36a68642adSMarcel Ziswiler 	}
37*53576c7bSMiquel Raynal 
38*53576c7bSMiquel Raynal 	nanddev_set_ecc_requirements(base, &requirements);
39a68642adSMarcel Ziswiler }
40a68642adSMarcel Ziswiler 
41a68642adSMarcel Ziswiler static int esmt_nand_init(struct nand_chip *chip)
42a68642adSMarcel Ziswiler {
43a68642adSMarcel Ziswiler 	if (nand_is_slc(chip))
447a1894a9SFrieder Schrempf 		/*
457a1894a9SFrieder Schrempf 		 * It is known that some ESMT SLC NANDs have been shipped
467a1894a9SFrieder Schrempf 		 * with the factory bad block markers in the first or last page
477a1894a9SFrieder Schrempf 		 * of the block, instead of the first or second page. To be on
487a1894a9SFrieder Schrempf 		 * the safe side, let's check all three locations.
497a1894a9SFrieder Schrempf 		 */
507a1894a9SFrieder Schrempf 		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
517a1894a9SFrieder Schrempf 				 NAND_BBM_LASTPAGE;
52a68642adSMarcel Ziswiler 
53a68642adSMarcel Ziswiler 	return 0;
54a68642adSMarcel Ziswiler }
55a68642adSMarcel Ziswiler 
56a68642adSMarcel Ziswiler const struct nand_manufacturer_ops esmt_nand_manuf_ops = {
57a68642adSMarcel Ziswiler 	.detect = esmt_nand_decode_id,
58a68642adSMarcel Ziswiler 	.init = esmt_nand_init,
59a68642adSMarcel Ziswiler };
60