diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-07-20 11:52:17 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-07-20 11:52:17 -0700 |
| commit | c43a20e4a520b37c2ef6d4f422de989992c9129f (patch) | |
| tree | 43a95786b614874d7a916e31968deb1b0960f9c6 /drivers/mtd/nand/raw/meson_nand.c | |
| parent | 9fa23750c6e591a6e095057ec07c81dddec0d72c (diff) | |
| parent | 78a0b13f5744bd270d0c2391973605d9960a402a (diff) | |
Merge tag 'mtd/for-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
Pull MTD updates from Miquel Raynal:
"Nothing stands out for this merge window, mostly minor fixes, such as
module descriptions, the use of debug macros and Makefile
improvements.
Raw NAND changes;
- The Freescale MXC driver has been converted to the newer
'->exec_op()' interface
- The meson driver now supports handling the boot ROM area with very
specific ECC needs
- Support for the iMX8QXP has been added to the GPMI driver
- The lpx32xx driver now can get the DMA channels using DT entries
- The Qcom binding has been improved to be more future proof by Rob
- And then there is the usual load of misc and minor changes
SPI-NAND changes:
- The Macronix vendor driver has been improved to support an extended
ID to avoid conflicting with older devices after an ID reuse issue
SPI NOR changes:
- Drop support for Xilinx S3AN flashes. These flashes are for the
very old Xilinx Spartan 3 FPGAs and they need some awkward code in
the core to support.
Drop support for these flashes, along with the special handling we
needed for them in the core like non-power-of-2 page size handling
and the .setup() callback.
- Fix regression for old w25q128 flashes without SFDP tables.
Commit 83e824a4a595 ("mtd: spi-nor: Correct flags for Winbond
w25q128") dropped support for such devices under the assumption
that they aren't being used anymore. Users have now surfaced [0] so
fix the regression by supporting both kind of devices.
- Core cleanups including removal of SPI_NOR_NO_FR flag and
simplification of spi_nor_get_flash_info()"
Link: https://lore.kernel.org/r/CALxbwRo_-9CaJmt7r7ELgu+vOcgk=xZcGHobnKf=oT2=u4d4aA@mail.gmail.com/ [0]
* tag 'mtd/for-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (28 commits)
mtd: rawnand: lpx32xx: Fix dma_request_chan() error checks
mtd: spinand: macronix: Add support for serial NAND flash
mtd: spinand: macronix: Add support for reading Device ID 2
mtd: rawnand: lpx32xx: Request DMA channels using DT entries
dt-bindings: mtd: qcom,nandc: Define properties at top-level
mtd: rawnand: intel: use 'time_left' variable with wait_for_completion_timeout()
mtd: rawnand: mxc: use 'time_left' variable with wait_for_completion_timeout()
mtd: rawnand: gpmi: add iMX8QXP support.
mtd: rawnand: gpmi: add 'support_edo_timing' in gpmi_devdata
mtd: cmdlinepart: Replace `dbg()` macro with `pr_debug()`
mtd: add missing MODULE_DESCRIPTION() macros
mtd: make mtd_test.c a separate module
dt-bindings: mtd: gpmi-nand: Add 'fsl,imx8qxp-gpmi-nand' compatible string
mtd: rawnand: cadence: remove unused struct 'ecc_info'
mtd: rawnand: mxc: support software ECC
mtd: rawnand: mxc: implement exec_op
mtd: rawnand: mxc: separate page read from ecc calc
mtd: spi-nor: winbond: fix w25q128 regression
mtd: spi-nor: simplify spi_nor_get_flash_info()
mtd: spi-nor: get rid of SPI_NOR_NO_FR
...
Diffstat (limited to 'drivers/mtd/nand/raw/meson_nand.c')
| -rw-r--r-- | drivers/mtd/nand/raw/meson_nand.c | 86 |
1 files changed, 59 insertions, 27 deletions
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 2a96a87cf79c..9eb5470344d0 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -35,6 +35,7 @@ #define NFC_CMD_RB BIT(20) #define NFC_CMD_SCRAMBLER_ENABLE BIT(19) #define NFC_CMD_SCRAMBLER_DISABLE 0 +#define NFC_CMD_SHORTMODE_ENABLE 1 #define NFC_CMD_SHORTMODE_DISABLE 0 #define NFC_CMD_RB_INT BIT(14) #define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) @@ -78,6 +79,8 @@ #define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N) #define DMA_ADDR_ALIGN 8 +#define NFC_SHORT_MODE_ECC_SZ 384 + #define ECC_CHECK_RETURN_FF (-1) #define NAND_CE0 (0xe << 10) @@ -125,6 +128,8 @@ struct meson_nfc_nand_chip { u32 twb; u32 tadl; u32 tbers_max; + u32 boot_pages; + u32 boot_page_step; u32 bch_mode; u8 *data_buf; @@ -298,28 +303,49 @@ static void meson_nfc_cmd_seed(struct meson_nfc *nfc, u32 seed) nfc->reg_base + NFC_REG_CMD); } -static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir, - int scrambler) +static int meson_nfc_is_boot_page(struct nand_chip *nand, int page) +{ + const struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + + return (nand->options & NAND_IS_BOOT_MEDIUM) && + !(page % meson_chip->boot_page_step) && + (page < meson_chip->boot_pages); +} + +static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir, int page) { + const struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); struct mtd_info *mtd = nand_to_mtd(nand); struct meson_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); - struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); - u32 bch = meson_chip->bch_mode, cmd; int len = mtd->writesize, pagesize, pages; + int scrambler; + u32 cmd; - pagesize = nand->ecc.size; + if (nand->options & NAND_NEED_SCRAMBLING) + scrambler = NFC_CMD_SCRAMBLER_ENABLE; + else + scrambler = NFC_CMD_SCRAMBLER_DISABLE; if (raw) { len = mtd->writesize + mtd->oobsize; cmd = len | scrambler | DMA_DIR(dir); - writel(cmd, nfc->reg_base + NFC_REG_CMD); - return; - } + } else if (meson_nfc_is_boot_page(nand, page)) { + pagesize = NFC_SHORT_MODE_ECC_SZ >> 3; + pages = mtd->writesize / 512; + + scrambler = NFC_CMD_SCRAMBLER_ENABLE; + cmd = CMDRWGEN(DMA_DIR(dir), scrambler, NFC_ECC_BCH8_1K, + NFC_CMD_SHORTMODE_ENABLE, pagesize, pages); + } else { + pagesize = nand->ecc.size >> 3; + pages = len / nand->ecc.size; - pages = len / nand->ecc.size; + cmd = CMDRWGEN(DMA_DIR(dir), scrambler, meson_chip->bch_mode, + NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); + } - cmd = CMDRWGEN(DMA_DIR(dir), scrambler, bch, - NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); + if (scrambler == NFC_CMD_SCRAMBLER_ENABLE) + meson_nfc_cmd_seed(nfc, page); writel(cmd, nfc->reg_base + NFC_REG_CMD); } @@ -743,14 +769,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand, if (ret) return ret; - if (nand->options & NAND_NEED_SCRAMBLING) { - meson_nfc_cmd_seed(nfc, page); - meson_nfc_cmd_access(nand, raw, DIRWRITE, - NFC_CMD_SCRAMBLER_ENABLE); - } else { - meson_nfc_cmd_access(nand, raw, DIRWRITE, - NFC_CMD_SCRAMBLER_DISABLE); - } + meson_nfc_cmd_access(nand, raw, DIRWRITE, page); cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; writel(cmd, nfc->reg_base + NFC_REG_CMD); @@ -829,14 +848,7 @@ static int meson_nfc_read_page_sub(struct nand_chip *nand, if (ret) return ret; - if (nand->options & NAND_NEED_SCRAMBLING) { - meson_nfc_cmd_seed(nfc, page); - meson_nfc_cmd_access(nand, raw, DIRREAD, - NFC_CMD_SCRAMBLER_ENABLE); - } else { - meson_nfc_cmd_access(nand, raw, DIRREAD, - NFC_CMD_SCRAMBLER_DISABLE); - } + meson_nfc_cmd_access(nand, raw, DIRREAD, page); ret = meson_nfc_wait_dma_finish(nfc); meson_nfc_check_ecc_pages_valid(nfc, nand, raw); @@ -1431,6 +1443,26 @@ meson_nfc_nand_chip_init(struct device *dev, if (ret) return ret; + if (nand->options & NAND_IS_BOOT_MEDIUM) { + ret = of_property_read_u32(np, "amlogic,boot-pages", + &meson_chip->boot_pages); + if (ret) { + dev_err(dev, "could not retrieve 'amlogic,boot-pages' property: %d", + ret); + nand_cleanup(nand); + return ret; + } + + ret = of_property_read_u32(np, "amlogic,boot-page-step", + &meson_chip->boot_page_step); + if (ret) { + dev_err(dev, "could not retrieve 'amlogic,boot-page-step' property: %d", + ret); + nand_cleanup(nand); + return ret; + } + } + ret = mtd_device_register(mtd, NULL, 0); if (ret) { dev_err(dev, "failed to register MTD device: %d\n", ret); |