SPI NAND fix:
- Wrong OOB layout for Winbond W25N01JW SPI NAND devices Raw NAND fixes: - Atmel raw NAND controller timings - Buffer handling in stm32_fmc2 driver - Error handling in Nuvoton's driver MTD devices fixes: - Wrong depends-on dependencies on the Intel DRM driver -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAmjC7bIACgkQJWrqGEe9 VoRFUwf6AnaDLEAvyyJF3mGPbL8zB9+3JVr78Zvpcy949QMvi17l5W07JBdZJkVI kByT0Y+XLFgSG1UtK1yCYSWM2achx33W1C1rp9D7Yp/yMZDCPoi4DcxMj+48A20s M58EjdCqlSRFmfl0D/w3UZ1vbDIo/cTInh+NpwHJktgW8JuNN1dzUaXyRG732pz8 wwC2wLKJwKGPquiEcCCuWKa2syoMAr440Gx21tB3hz/ypGj33+I9Hoj7N4sMjo+b 0ZZPq0lwMkwwhILHNybaOYIKmbK57KHRJYQrcUvkzQZA/swxK91vO13MxwIAylN6 2g2hM5x8TgKH17VNdxexU6eq0tkN/A== =rIOi -----END PGP SIGNATURE----- Merge tag 'mtd/fixes-for-6.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux Pull mtd fixes from Miquel Raynal: "SPI NAND fix: - Wrong OOB layout for Winbond W25N01JW SPI NAND devices Raw NAND fixes: - Atmel raw NAND controller timings - Buffer handling in stm32_fmc2 driver - Error handling in Nuvoton's driver MTD devices fixes: - Wrong depends-on dependencies on the Intel DRM driver * tag 'mtd/fixes-for-6.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: mtd: spinand: winbond: Fix oob_layout for W25N01JW mtd: nand: raw: atmel: Respect tAR, tCLR in read setup timing mtd: rawnand: stm32_fmc2: fix ECC overwrite mtd: rawnand: stm32_fmc2: avoid overlapping mappings on ECC buffer mtd: rawnand: nuvoton: Fix an error handling path in ma35_nand_chips_init() mtd: MTD_INTEL_DG should depend on DRM_I915 or DRM_XEpull/824/head
commit
320475fbd5
|
|
@ -185,8 +185,8 @@ config MTD_POWERNV_FLASH
|
|||
|
||||
config MTD_INTEL_DG
|
||||
tristate "Intel Discrete Graphics non-volatile memory driver"
|
||||
depends on AUXILIARY_BUS
|
||||
depends on MTD
|
||||
depends on AUXILIARY_BUS && MTD
|
||||
depends on DRM_I915!=n || DRM_XE!=n || COMPILE_TEST
|
||||
help
|
||||
This provides an MTD device to access Intel Discrete Graphics
|
||||
non-volatile memory.
|
||||
|
|
|
|||
|
|
@ -1377,14 +1377,24 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Read setup timing depends on the operation done on the NAND:
|
||||
*
|
||||
* NRD_SETUP = max(tAR, tCLR)
|
||||
*/
|
||||
timeps = max(conf->timings.sdr.tAR_min, conf->timings.sdr.tCLR_min);
|
||||
ncycles = DIV_ROUND_UP(timeps, mckperiodps);
|
||||
totalcycles += ncycles;
|
||||
ret = atmel_smc_cs_conf_set_setup(smcconf, ATMEL_SMC_NRD_SHIFT, ncycles);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* The read cycle timing is directly matching tRC, but is also
|
||||
* dependent on the setup and hold timings we calculated earlier,
|
||||
* which gives:
|
||||
*
|
||||
* NRD_CYCLE = max(tRC, NRD_PULSE + NRD_HOLD)
|
||||
*
|
||||
* NRD_SETUP is always 0.
|
||||
* NRD_CYCLE = max(tRC, NRD_SETUP + NRD_PULSE + NRD_HOLD)
|
||||
*/
|
||||
ncycles = DIV_ROUND_UP(conf->timings.sdr.tRC_min, mckperiodps);
|
||||
ncycles = max(totalcycles, ncycles);
|
||||
|
|
|
|||
|
|
@ -935,10 +935,10 @@ static void ma35_chips_cleanup(struct ma35_nand_info *nand)
|
|||
|
||||
static int ma35_nand_chips_init(struct device *dev, struct ma35_nand_info *nand)
|
||||
{
|
||||
struct device_node *np = dev->of_node, *nand_np;
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
|
||||
for_each_child_of_node(np, nand_np) {
|
||||
for_each_child_of_node_scoped(np, nand_np) {
|
||||
ret = ma35_nand_chip_init(dev, nand, nand_np);
|
||||
if (ret) {
|
||||
ma35_chips_cleanup(nand);
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ struct stm32_fmc2_nfc {
|
|||
struct sg_table dma_data_sg;
|
||||
struct sg_table dma_ecc_sg;
|
||||
u8 *ecc_buf;
|
||||
dma_addr_t dma_ecc_addr;
|
||||
int dma_ecc_len;
|
||||
u32 tx_dma_max_burst;
|
||||
u32 rx_dma_max_burst;
|
||||
|
|
@ -902,17 +903,10 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
|
||||
if (!write_data && !raw) {
|
||||
/* Configure DMA ECC status */
|
||||
p = nfc->ecc_buf;
|
||||
for_each_sg(nfc->dma_ecc_sg.sgl, sg, eccsteps, s) {
|
||||
sg_set_buf(sg, p, nfc->dma_ecc_len);
|
||||
p += nfc->dma_ecc_len;
|
||||
}
|
||||
|
||||
ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
|
||||
eccsteps, dma_data_dir);
|
||||
if (!ret) {
|
||||
ret = -EIO;
|
||||
goto err_unmap_data;
|
||||
sg_dma_address(sg) = nfc->dma_ecc_addr +
|
||||
s * nfc->dma_ecc_len;
|
||||
sg_dma_len(sg) = nfc->dma_ecc_len;
|
||||
}
|
||||
|
||||
desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch,
|
||||
|
|
@ -921,7 +915,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
DMA_PREP_INTERRUPT);
|
||||
if (!desc_ecc) {
|
||||
ret = -ENOMEM;
|
||||
goto err_unmap_ecc;
|
||||
goto err_unmap_data;
|
||||
}
|
||||
|
||||
reinit_completion(&nfc->dma_ecc_complete);
|
||||
|
|
@ -929,7 +923,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
desc_ecc->callback_param = &nfc->dma_ecc_complete;
|
||||
ret = dma_submit_error(dmaengine_submit(desc_ecc));
|
||||
if (ret)
|
||||
goto err_unmap_ecc;
|
||||
goto err_unmap_data;
|
||||
|
||||
dma_async_issue_pending(nfc->dma_ecc_ch);
|
||||
}
|
||||
|
|
@ -949,7 +943,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
if (!write_data && !raw)
|
||||
dmaengine_terminate_all(nfc->dma_ecc_ch);
|
||||
ret = -ETIMEDOUT;
|
||||
goto err_unmap_ecc;
|
||||
goto err_unmap_data;
|
||||
}
|
||||
|
||||
/* Wait DMA data transfer completion */
|
||||
|
|
@ -969,11 +963,6 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
}
|
||||
}
|
||||
|
||||
err_unmap_ecc:
|
||||
if (!write_data && !raw)
|
||||
dma_unmap_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
|
||||
eccsteps, dma_data_dir);
|
||||
|
||||
err_unmap_data:
|
||||
dma_unmap_sg(nfc->dev, nfc->dma_data_sg.sgl, eccsteps, dma_data_dir);
|
||||
|
||||
|
|
@ -996,9 +985,21 @@ static int stm32_fmc2_nfc_seq_write(struct nand_chip *chip, const u8 *buf,
|
|||
|
||||
/* Write oob */
|
||||
if (oob_required) {
|
||||
ret = nand_change_write_column_op(chip, mtd->writesize,
|
||||
chip->oob_poi, mtd->oobsize,
|
||||
false);
|
||||
unsigned int offset_in_page = mtd->writesize;
|
||||
const void *buf = chip->oob_poi;
|
||||
unsigned int len = mtd->oobsize;
|
||||
|
||||
if (!raw) {
|
||||
struct mtd_oob_region oob_free;
|
||||
|
||||
mtd_ooblayout_free(mtd, 0, &oob_free);
|
||||
offset_in_page += oob_free.offset;
|
||||
buf += oob_free.offset;
|
||||
len = oob_free.length;
|
||||
}
|
||||
|
||||
ret = nand_change_write_column_op(chip, offset_in_page,
|
||||
buf, len, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1610,7 +1611,8 @@ static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc)
|
|||
return ret;
|
||||
|
||||
/* Allocate a buffer to store ECC status registers */
|
||||
nfc->ecc_buf = devm_kzalloc(nfc->dev, FMC2_MAX_ECC_BUF_LEN, GFP_KERNEL);
|
||||
nfc->ecc_buf = dmam_alloc_coherent(nfc->dev, FMC2_MAX_ECC_BUF_LEN,
|
||||
&nfc->dma_ecc_addr, GFP_KERNEL);
|
||||
if (!nfc->ecc_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -176,6 +176,36 @@ static const struct mtd_ooblayout_ops w25n02kv_ooblayout = {
|
|||
.free = w25n02kv_ooblayout_free,
|
||||
};
|
||||
|
||||
static int w25n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section > 3)
|
||||
return -ERANGE;
|
||||
|
||||
region->offset = (16 * section) + 12;
|
||||
region->length = 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int w25n01jw_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section > 3)
|
||||
return -ERANGE;
|
||||
|
||||
region->offset = (16 * section);
|
||||
region->length = 12;
|
||||
|
||||
/* Extract BBM */
|
||||
if (!section) {
|
||||
region->offset += 2;
|
||||
region->length -= 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
|
|
@ -206,6 +236,11 @@ static int w35n01jw_ooblayout_free(struct mtd_info *mtd, int section,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtd_ooblayout_ops w25n01jw_ooblayout = {
|
||||
.ecc = w25n01jw_ooblayout_ecc,
|
||||
.free = w25n01jw_ooblayout_free,
|
||||
};
|
||||
|
||||
static const struct mtd_ooblayout_ops w35n01jw_ooblayout = {
|
||||
.ecc = w35n01jw_ooblayout_ecc,
|
||||
.free = w35n01jw_ooblayout_free,
|
||||
|
|
@ -394,7 +429,7 @@ static const struct spinand_info winbond_spinand_table[] = {
|
|||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
0,
|
||||
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
|
||||
SPINAND_ECCINFO(&w25n01jw_ooblayout, NULL),
|
||||
SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)),
|
||||
SPINAND_INFO("W25N01KV", /* 3.3V */
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),
|
||||
|
|
|
|||
Loading…
Reference in New Issue