162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2018 Toradex AG
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: Marcel Ziswiler <marcel.ziswiler@toradex.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/mtd/rawnand.h>
962306a36Sopenharmony_ci#include "internals.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistatic void esmt_nand_decode_id(struct nand_chip *chip)
1262306a36Sopenharmony_ci{
1362306a36Sopenharmony_ci	struct nand_device *base = &chip->base;
1462306a36Sopenharmony_ci	struct nand_ecc_props requirements = {};
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	nand_decode_ext_id(chip);
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	/* Extract ECC requirements from 5th id byte. */
1962306a36Sopenharmony_ci	if (chip->id.len >= 5 && nand_is_slc(chip)) {
2062306a36Sopenharmony_ci		requirements.step_size = 512;
2162306a36Sopenharmony_ci		switch (chip->id.data[4] & 0x3) {
2262306a36Sopenharmony_ci		case 0x0:
2362306a36Sopenharmony_ci			requirements.strength = 4;
2462306a36Sopenharmony_ci			break;
2562306a36Sopenharmony_ci		case 0x1:
2662306a36Sopenharmony_ci			requirements.strength = 2;
2762306a36Sopenharmony_ci			break;
2862306a36Sopenharmony_ci		case 0x2:
2962306a36Sopenharmony_ci			requirements.strength = 1;
3062306a36Sopenharmony_ci			break;
3162306a36Sopenharmony_ci		default:
3262306a36Sopenharmony_ci			WARN(1, "Could not get ECC info");
3362306a36Sopenharmony_ci			requirements.step_size = 0;
3462306a36Sopenharmony_ci			break;
3562306a36Sopenharmony_ci		}
3662306a36Sopenharmony_ci	}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	nanddev_set_ecc_requirements(base, &requirements);
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic int esmt_nand_init(struct nand_chip *chip)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	if (nand_is_slc(chip))
4462306a36Sopenharmony_ci		/*
4562306a36Sopenharmony_ci		 * It is known that some ESMT SLC NANDs have been shipped
4662306a36Sopenharmony_ci		 * with the factory bad block markers in the first or last page
4762306a36Sopenharmony_ci		 * of the block, instead of the first or second page. To be on
4862306a36Sopenharmony_ci		 * the safe side, let's check all three locations.
4962306a36Sopenharmony_ci		 */
5062306a36Sopenharmony_ci		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
5162306a36Sopenharmony_ci				 NAND_BBM_LASTPAGE;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	return 0;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ciconst struct nand_manufacturer_ops esmt_nand_manuf_ops = {
5762306a36Sopenharmony_ci	.detect = esmt_nand_decode_id,
5862306a36Sopenharmony_ci	.init = esmt_nand_init,
5962306a36Sopenharmony_ci};
60