18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2018 Toradex AG
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author: Marcel Ziswiler <marcel.ziswiler@toradex.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/mtd/rawnand.h>
98c2ecf20Sopenharmony_ci#include "internals.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistatic void esmt_nand_decode_id(struct nand_chip *chip)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	struct nand_device *base = &chip->base;
148c2ecf20Sopenharmony_ci	struct nand_ecc_props requirements = {};
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	nand_decode_ext_id(chip);
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	/* Extract ECC requirements from 5th id byte. */
198c2ecf20Sopenharmony_ci	if (chip->id.len >= 5 && nand_is_slc(chip)) {
208c2ecf20Sopenharmony_ci		requirements.step_size = 512;
218c2ecf20Sopenharmony_ci		switch (chip->id.data[4] & 0x3) {
228c2ecf20Sopenharmony_ci		case 0x0:
238c2ecf20Sopenharmony_ci			requirements.strength = 4;
248c2ecf20Sopenharmony_ci			break;
258c2ecf20Sopenharmony_ci		case 0x1:
268c2ecf20Sopenharmony_ci			requirements.strength = 2;
278c2ecf20Sopenharmony_ci			break;
288c2ecf20Sopenharmony_ci		case 0x2:
298c2ecf20Sopenharmony_ci			requirements.strength = 1;
308c2ecf20Sopenharmony_ci			break;
318c2ecf20Sopenharmony_ci		default:
328c2ecf20Sopenharmony_ci			WARN(1, "Could not get ECC info");
338c2ecf20Sopenharmony_ci			requirements.step_size = 0;
348c2ecf20Sopenharmony_ci			break;
358c2ecf20Sopenharmony_ci		}
368c2ecf20Sopenharmony_ci	}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	nanddev_set_ecc_requirements(base, &requirements);
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic int esmt_nand_init(struct nand_chip *chip)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	if (nand_is_slc(chip))
448c2ecf20Sopenharmony_ci		/*
458c2ecf20Sopenharmony_ci		 * It is known that some ESMT SLC NANDs have been shipped
468c2ecf20Sopenharmony_ci		 * with the factory bad block markers in the first or last page
478c2ecf20Sopenharmony_ci		 * of the block, instead of the first or second page. To be on
488c2ecf20Sopenharmony_ci		 * the safe side, let's check all three locations.
498c2ecf20Sopenharmony_ci		 */
508c2ecf20Sopenharmony_ci		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
518c2ecf20Sopenharmony_ci				 NAND_BBM_LASTPAGE;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	return 0;
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ciconst struct nand_manufacturer_ops esmt_nand_manuf_ops = {
578c2ecf20Sopenharmony_ci	.detect = esmt_nand_decode_id,
588c2ecf20Sopenharmony_ci	.init = esmt_nand_init,
598c2ecf20Sopenharmony_ci};
60