Commit f6176471 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mtd/fixes-for-6.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull MTD fixes from Miquel Raynal:
 "In the raw NAND subsystem, the major fix prevents using cached reads
  with devices not supporting it. There was two bug reports about this.

  Apart from that, three drivers (pl353, arasan and marvell) could
  sometimes hide page program failures due to their their own program
  page helper not being fully compliant with the specification (many
  drivers use the default helpers shared by the core). Adding a missing
  check prevents these situation.

  Finally, the Qualcomm driver had a broken error path.

  In the SPI-NAND subsystem one Micron device used a wrong bitmak
  reporting possibly corrupted ECC status.

  Finally, the physmap-core got stripped from its map_rom fallback by
  mistake, this feature is added back"

* tag 'mtd/fixes-for-6.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: rawnand: Ensure the nand chip supports cached reads
  mtd: rawnand: qcom: Unmap the right resource upon probe failure
  mtd: rawnand: pl353: Ensure program page operations are successful
  mtd: rawnand: arasan: Ensure program page operations are successful
  mtd: spinand: micron: correct bitmask for ecc status
  mtd: physmap-core: Restore map_rom fallback
  mtd: rawnand: marvell: Ensure program page operations are successful
parents 7da6c042 f6ca3fb6
...@@ -551,6 +551,17 @@ static int physmap_flash_probe(struct platform_device *dev) ...@@ -551,6 +551,17 @@ static int physmap_flash_probe(struct platform_device *dev)
if (info->probe_type) { if (info->probe_type) {
info->mtds[i] = do_map_probe(info->probe_type, info->mtds[i] = do_map_probe(info->probe_type,
&info->maps[i]); &info->maps[i]);
/* Fall back to mapping region as ROM */
if (!info->mtds[i] && IS_ENABLED(CONFIG_MTD_ROM) &&
strcmp(info->probe_type, "map_rom")) {
dev_warn(&dev->dev,
"map_probe() failed for type %s\n",
info->probe_type);
info->mtds[i] = do_map_probe("map_rom",
&info->maps[i]);
}
} else { } else {
int j; int j;
......
...@@ -515,6 +515,7 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, ...@@ -515,6 +515,7 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
unsigned int len = mtd->writesize + (oob_required ? mtd->oobsize : 0); unsigned int len = mtd->writesize + (oob_required ? mtd->oobsize : 0);
dma_addr_t dma_addr; dma_addr_t dma_addr;
u8 status;
int ret; int ret;
struct anfc_op nfc_op = { struct anfc_op nfc_op = {
.pkt_reg = .pkt_reg =
...@@ -561,10 +562,21 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, ...@@ -561,10 +562,21 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
} }
/* Spare data is not protected */ /* Spare data is not protected */
if (oob_required) if (oob_required) {
ret = nand_write_oob_std(chip, page); ret = nand_write_oob_std(chip, page);
if (ret)
return ret;
}
return ret; /* Check write status on the chip side */
ret = nand_status_op(chip, &status);
if (ret)
return ret;
if (status & NAND_STATUS_FAIL)
return -EIO;
return 0;
} }
static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
......
...@@ -1165,6 +1165,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, ...@@ -1165,6 +1165,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
.ndcb[2] = NDCB2_ADDR5_PAGE(page), .ndcb[2] = NDCB2_ADDR5_PAGE(page),
}; };
unsigned int oob_bytes = lt->spare_bytes + (raw ? lt->ecc_bytes : 0); unsigned int oob_bytes = lt->spare_bytes + (raw ? lt->ecc_bytes : 0);
u8 status;
int ret; int ret;
/* NFCv2 needs more information about the operation being executed */ /* NFCv2 needs more information about the operation being executed */
...@@ -1198,7 +1199,18 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, ...@@ -1198,7 +1199,18 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
ret = marvell_nfc_wait_op(chip, ret = marvell_nfc_wait_op(chip,
PSEC_TO_MSEC(sdr->tPROG_max)); PSEC_TO_MSEC(sdr->tPROG_max));
return ret; if (ret)
return ret;
/* Check write status on the chip side */
ret = nand_status_op(chip, &status);
if (ret)
return ret;
if (status & NAND_STATUS_FAIL)
return -EIO;
return 0;
} }
static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip, static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip,
...@@ -1627,6 +1639,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, ...@@ -1627,6 +1639,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
int data_len = lt->data_bytes; int data_len = lt->data_bytes;
int spare_len = lt->spare_bytes; int spare_len = lt->spare_bytes;
int chunk, ret; int chunk, ret;
u8 status;
marvell_nfc_select_target(chip, chip->cur_cs); marvell_nfc_select_target(chip, chip->cur_cs);
...@@ -1663,6 +1676,14 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, ...@@ -1663,6 +1676,14 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
if (ret) if (ret)
return ret; return ret;
/* Check write status on the chip side */
ret = nand_status_op(chip, &status);
if (ret)
return ret;
if (status & NAND_STATUS_FAIL)
return -EIO;
return 0; return 0;
} }
......
...@@ -5110,6 +5110,9 @@ static void rawnand_check_cont_read_support(struct nand_chip *chip) ...@@ -5110,6 +5110,9 @@ static void rawnand_check_cont_read_support(struct nand_chip *chip)
{ {
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
if (!chip->parameters.supports_read_cache)
return;
if (chip->read_retries) if (chip->read_retries)
return; return;
......
...@@ -94,6 +94,9 @@ int nand_jedec_detect(struct nand_chip *chip) ...@@ -94,6 +94,9 @@ int nand_jedec_detect(struct nand_chip *chip)
goto free_jedec_param_page; goto free_jedec_param_page;
} }
if (p->opt_cmd[0] & JEDEC_OPT_CMD_READ_CACHE)
chip->parameters.supports_read_cache = true;
memorg->pagesize = le32_to_cpu(p->byte_per_page); memorg->pagesize = le32_to_cpu(p->byte_per_page);
mtd->writesize = memorg->pagesize; mtd->writesize = memorg->pagesize;
......
...@@ -303,6 +303,9 @@ int nand_onfi_detect(struct nand_chip *chip) ...@@ -303,6 +303,9 @@ int nand_onfi_detect(struct nand_chip *chip)
ONFI_FEATURE_ADDR_TIMING_MODE, 1); ONFI_FEATURE_ADDR_TIMING_MODE, 1);
} }
if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_READ_CACHE)
chip->parameters.supports_read_cache = true;
onfi = kzalloc(sizeof(*onfi), GFP_KERNEL); onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
if (!onfi) { if (!onfi) {
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -511,6 +511,7 @@ static int pl35x_nand_write_page_hwecc(struct nand_chip *chip, ...@@ -511,6 +511,7 @@ static int pl35x_nand_write_page_hwecc(struct nand_chip *chip,
u32 addr1 = 0, addr2 = 0, row; u32 addr1 = 0, addr2 = 0, row;
u32 cmd_addr; u32 cmd_addr;
int i, ret; int i, ret;
u8 status;
ret = pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_APB); ret = pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_APB);
if (ret) if (ret)
...@@ -563,6 +564,14 @@ static int pl35x_nand_write_page_hwecc(struct nand_chip *chip, ...@@ -563,6 +564,14 @@ static int pl35x_nand_write_page_hwecc(struct nand_chip *chip,
if (ret) if (ret)
goto disable_ecc_engine; goto disable_ecc_engine;
/* Check write status on the chip side */
ret = nand_status_op(chip, &status);
if (ret)
goto disable_ecc_engine;
if (status & NAND_STATUS_FAIL)
ret = -EIO;
disable_ecc_engine: disable_ecc_engine:
pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS);
......
...@@ -3444,7 +3444,7 @@ static int qcom_nandc_probe(struct platform_device *pdev) ...@@ -3444,7 +3444,7 @@ static int qcom_nandc_probe(struct platform_device *pdev)
err_aon_clk: err_aon_clk:
clk_disable_unprepare(nandc->core_clk); clk_disable_unprepare(nandc->core_clk);
err_core_clk: err_core_clk:
dma_unmap_resource(dev, res->start, resource_size(res), dma_unmap_resource(dev, nandc->base_dma, resource_size(res),
DMA_BIDIRECTIONAL, 0); DMA_BIDIRECTIONAL, 0);
return ret; return ret;
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#define SPINAND_MFR_MICRON 0x2c #define SPINAND_MFR_MICRON 0x2c
#define MICRON_STATUS_ECC_MASK GENMASK(7, 4) #define MICRON_STATUS_ECC_MASK GENMASK(6, 4)
#define MICRON_STATUS_ECC_NO_BITFLIPS (0 << 4) #define MICRON_STATUS_ECC_NO_BITFLIPS (0 << 4)
#define MICRON_STATUS_ECC_1TO3_BITFLIPS (1 << 4) #define MICRON_STATUS_ECC_1TO3_BITFLIPS (1 << 4)
#define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4) #define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4)
......
...@@ -21,6 +21,9 @@ struct jedec_ecc_info { ...@@ -21,6 +21,9 @@ struct jedec_ecc_info {
/* JEDEC features */ /* JEDEC features */
#define JEDEC_FEATURE_16_BIT_BUS (1 << 0) #define JEDEC_FEATURE_16_BIT_BUS (1 << 0)
/* JEDEC Optional Commands */
#define JEDEC_OPT_CMD_READ_CACHE BIT(1)
struct nand_jedec_params { struct nand_jedec_params {
/* rev info and features block */ /* rev info and features block */
/* 'J' 'E' 'S' 'D' */ /* 'J' 'E' 'S' 'D' */
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#define ONFI_SUBFEATURE_PARAM_LEN 4 #define ONFI_SUBFEATURE_PARAM_LEN 4
/* ONFI optional commands SET/GET FEATURES supported? */ /* ONFI optional commands SET/GET FEATURES supported? */
#define ONFI_OPT_CMD_READ_CACHE BIT(1)
#define ONFI_OPT_CMD_SET_GET_FEATURES BIT(2) #define ONFI_OPT_CMD_SET_GET_FEATURES BIT(2)
struct nand_onfi_params { struct nand_onfi_params {
......
...@@ -225,6 +225,7 @@ struct gpio_desc; ...@@ -225,6 +225,7 @@ struct gpio_desc;
* struct nand_parameters - NAND generic parameters from the parameter page * struct nand_parameters - NAND generic parameters from the parameter page
* @model: Model name * @model: Model name
* @supports_set_get_features: The NAND chip supports setting/getting features * @supports_set_get_features: The NAND chip supports setting/getting features
* @supports_read_cache: The NAND chip supports read cache operations
* @set_feature_list: Bitmap of features that can be set * @set_feature_list: Bitmap of features that can be set
* @get_feature_list: Bitmap of features that can be get * @get_feature_list: Bitmap of features that can be get
* @onfi: ONFI specific parameters * @onfi: ONFI specific parameters
...@@ -233,6 +234,7 @@ struct nand_parameters { ...@@ -233,6 +234,7 @@ struct nand_parameters {
/* Generic parameters */ /* Generic parameters */
const char *model; const char *model;
bool supports_set_get_features; bool supports_set_get_features;
bool supports_read_cache;
DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER); DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER);
DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER); DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment