Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97baea1e authored by Miquel Raynal's avatar Miquel Raynal Committed by Boris Brezillon
Browse files

mtd: rawnand: use wrappers to call onfi GET/SET_FEATURES



Prepare the fact that some features managed by GET/SET_FEATURES could be
overloaded by vendor code. To handle this logic, use new wrappers
instead of directly call the ->get/set_features() hooks.

Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@bootlin.com>
parent b958758e
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -934,15 +934,13 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)

	/* [1] send SET FEATURE command to NAND */
	feature[0] = mode;
	ret = nand->set_features(mtd, nand,
				 ONFI_FEATURE_ADDR_TIMING_MODE, feature);
	ret = nand_set_features(nand, ONFI_FEATURE_ADDR_TIMING_MODE, feature);
	if (ret)
		goto err_out;

	/* [2] send GET FEATURE command to double-check the timing mode */
	memset(feature, 0, ONFI_SUBFEATURE_PARAM_LEN);
	ret = nand->get_features(mtd, nand,
				 ONFI_FEATURE_ADDR_TIMING_MODE, feature);
	ret = nand_get_features(nand, ONFI_FEATURE_ADDR_TIMING_MODE, feature);
	if (ret || feature[0] != mode)
		goto err_out;

+59 −30
Original line number Diff line number Diff line
@@ -1160,6 +1160,55 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
	return status;
}

static bool nand_supports_set_get_features(struct nand_chip *chip)
{
	return (chip->onfi_version &&
		(le16_to_cpu(chip->onfi_params.opt_cmd) &
		 ONFI_OPT_CMD_SET_GET_FEATURES));
}

/**
 * nand_get_features - wrapper to perform a GET_FEATURE
 * @chip: NAND chip info structure
 * @addr: feature address
 * @subfeature_param: the subfeature parameters, a four bytes array
 *
 * Returns 0 for success, a negative error otherwise. Returns -ENOTSUPP if the
 * operation cannot be handled.
 */
int nand_get_features(struct nand_chip *chip, int addr,
		      u8 *subfeature_param)
{
	struct mtd_info *mtd = nand_to_mtd(chip);

	if (!nand_supports_set_get_features(chip))
		return -ENOTSUPP;

	return chip->get_features(mtd, chip, addr, subfeature_param);
}
EXPORT_SYMBOL_GPL(nand_get_features);

/**
 * nand_set_features - wrapper to perform a SET_FEATURE
 * @chip: NAND chip info structure
 * @addr: feature address
 * @subfeature_param: the subfeature parameters, a four bytes array
 *
 * Returns 0 for success, a negative error otherwise. Returns -ENOTSUPP if the
 * operation cannot be handled.
 */
int nand_set_features(struct nand_chip *chip, int addr,
		      u8 *subfeature_param)
{
	struct mtd_info *mtd = nand_to_mtd(chip);

	if (!nand_supports_set_get_features(chip))
		return -ENOTSUPP;

	return chip->set_features(mtd, chip, addr, subfeature_param);
}
EXPORT_SYMBOL_GPL(nand_set_features);

/**
 * nand_reset_data_interface - Reset data interface and timings
 * @chip: The NAND chip
@@ -1215,32 +1264,22 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
		chip->onfi_timing_mode_default,
	};
	int ret;

	if (!chip->setup_data_interface)
		return 0;

	/*
	 * Ensure the timing mode has been changed on the chip side
	 * before changing timings on the controller side.
	 */
	if (chip->onfi_version &&
	    (le16_to_cpu(chip->onfi_params.opt_cmd) &
	     ONFI_OPT_CMD_SET_GET_FEATURES)) {
		u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
			chip->onfi_timing_mode_default,
		};

		ret = chip->set_features(mtd, chip,
					 ONFI_FEATURE_ADDR_TIMING_MODE,
	/* Change the mode on the chip side */
	ret = nand_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE,
				tmode_param);
	if (ret)
			goto err;
	}

	ret = chip->setup_data_interface(mtd, chipnr, &chip->data_interface);
err:
		return ret;

	/* Change the mode on the controller side */
	return chip->setup_data_interface(mtd, chipnr, &chip->data_interface);
}

/**
@@ -4779,11 +4818,6 @@ static int nand_default_set_features(struct mtd_info *mtd,
				     struct nand_chip *chip, int addr,
				     uint8_t *subfeature_param)
{
	if (!chip->onfi_version ||
	    !(le16_to_cpu(chip->onfi_params.opt_cmd)
	      & ONFI_OPT_CMD_SET_GET_FEATURES))
		return -EINVAL;

	return nand_set_features_op(chip, addr, subfeature_param);
}

@@ -4798,11 +4832,6 @@ static int nand_default_get_features(struct mtd_info *mtd,
				     struct nand_chip *chip, int addr,
				     uint8_t *subfeature_param)
{
	if (!chip->onfi_version ||
	    !(le16_to_cpu(chip->onfi_params.opt_cmd)
	      & ONFI_OPT_CMD_SET_GET_FEATURES))
		return -EINVAL;

	return nand_get_features_op(chip, addr, subfeature_param);
}

+10 −8
Original line number Diff line number Diff line
@@ -48,8 +48,7 @@ static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
	struct nand_chip *chip = mtd_to_nand(mtd);
	u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};

	return chip->set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
				  feature);
	return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
}

/*
@@ -108,8 +107,7 @@ static int micron_nand_on_die_ecc_setup(struct nand_chip *chip, bool enable)
	if (enable)
		feature[0] |= ONFI_FEATURE_ON_DIE_ECC_EN;

	return chip->set_features(nand_to_mtd(chip), chip,
				  ONFI_FEATURE_ON_DIE_ECC, feature);
	return nand_set_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
}

static int
@@ -219,8 +217,10 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
	if (ret)
		return MICRON_ON_DIE_UNSUPPORTED;

	chip->get_features(nand_to_mtd(chip), chip,
			   ONFI_FEATURE_ON_DIE_ECC, feature);
	ret = nand_get_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
	if (ret < 0)
		return ret;

	if ((feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN) == 0)
		return MICRON_ON_DIE_UNSUPPORTED;

@@ -228,8 +228,10 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
	if (ret)
		return MICRON_ON_DIE_UNSUPPORTED;

	chip->get_features(nand_to_mtd(chip), chip,
			   ONFI_FEATURE_ON_DIE_ECC, feature);
	ret = nand_get_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
	if (ret < 0)
		return ret;

	if (feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN)
		return MICRON_ON_DIE_MANDATORY;

+3 −0
Original line number Diff line number Diff line
@@ -1629,6 +1629,9 @@ int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page);
int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
			   int page);

/* Wrapper to use in order for controllers/vendors to GET/SET FEATURES */
int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
/* Stub used by drivers that do not support GET/SET FEATURES operations */
int nand_get_set_features_notsupp(struct mtd_info *mtd, struct nand_chip *chip,
				  int addr, u8 *subfeature_param);