Re: [PATCH v2 3/3] mtd: rawnand: meson: read/write access for boot ROM pages
Arseniy Krasnov <[email protected]>
| Newsgroups | io.groups.u-boot-amlogic,org.u-boot-project.lists.u-boot |
|---|---|
| Message-ID | <[email protected]> |
On 26.08.2024 10:16, Michael Nazzareno Trimarchi wrote: > Hi > > On Mon, Aug 26, 2024 at 8:17 AM Arseniy Krasnov > <[email protected]> wrote: >> >> Boot ROM on Meson needs some pages to be read/written in a special mode: >> 384 byte ECC mode (so called "short" by Amlogic) and with scrambling >> enabled. Such pages are located on the chip in the following way (for >> example): >> >> [ p0 ][ p1 ][ p2 ][ p3 ][ p4 ][ p5 ][ p6 ][ p7 ] ... [ pN ] >> ^ ^ ^ ^ >> >> pX is page number "X". "^" means "special" page used by boot ROM - e.g. >> every 2nd page in the range of [0, 7]. Step (2 here) and last page in >> range is read from the device tree. >> >> Signed-off-by: Arseniy Krasnov <[email protected]> >> --- >> drivers/mtd/nand/raw/meson_nand.c | 56 +++++++++++++++++++++++++------ >> 1 file changed, 46 insertions(+), 10 deletions(-) >> >> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c >> index 19f005202b..54ea035d8d 100644 >> --- a/drivers/mtd/nand/raw/meson_nand.c >> +++ b/drivers/mtd/nand/raw/meson_nand.c >> @@ -40,6 +40,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 NFC_SHORT_MODE_ECC_SZ 384 >> + >> #define ECC_CHECK_RETURN_FF -1 >> >> #define NAND_CE0 (0xe << 10) >> @@ -141,6 +144,8 @@ >> struct meson_nfc_nand_chip { >> struct list_head node; >> struct nand_chip nand; >> + u32 boot_pages; >> + u32 boot_page_step; >> >> u32 bch_mode; >> u8 *data_buf; >> @@ -229,33 +234,46 @@ static void meson_nfc_cmd_seed(const struct meson_nfc *nfc, u32 seed) >> nfc->reg_base + NFC_REG_CMD); >> } >> >> +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, bool 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); >> const struct meson_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); >> - const 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; >> >> if (nand->options & NAND_NEED_SCRAMBLING) >> scrambler = NFC_CMD_SCRAMBLER_ENABLE; >> else >> scrambler = NFC_CMD_SCRAMBLER_DISABLE; >> > > scrambler depends on NAND_NEED_SCRAMBLING so suppose > that is not set > > scrambler = NAND_NEED_SCRAMBLING; > >> - pagesize = nand->ecc.size; >> - >> 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)) { > > Now here you seems that you don't care anymore about this option and check > only meson_nfc_is_boot_page > > Is something am I missing? Idea is the following IIUC: such boot pages could be read in ECC mode only with enabled scrambling - otherwise we get ECC error. Or we need to read it in raw mode. So: if (read page in raw mode) { use scrambler as provided } else if (read boot page in ECC mode) { force scrambling mode + NFC_ECC_BCH8_1K + NFC_CMD_SHORTMODE_ENABLE } else { //we read non-boot page in ECC mode use scrambler as provided } Thanks > > Michael > >> + pagesize = NFC_SHORT_MODE_ECC_SZ >> 3; >> + pages = mtd->writesize / 512; >> >> - pages = len / nand->ecc.size; >> + 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; >> >> - cmd = CMDRWGEN(DMA_DIR(dir), scrambler, bch, >> - NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); >> + cmd = CMDRWGEN(DMA_DIR(dir), scrambler, meson_chip->bch_mode, >> + NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); >> + } >> >> if (scrambler == NFC_CMD_SCRAMBLER_ENABLE) >> meson_nfc_cmd_seed(nfc, page); >> @@ -1132,6 +1150,24 @@ static int meson_nfc_nand_chip_init(struct udevice *dev, struct meson_nfc *nfc, >> goto err_chip_buf_free; >> } >> >> + if (nand->options & NAND_IS_BOOT_MEDIUM) { >> + ret = ofnode_read_u32(node, "amlogic,boot-pages", >> + &meson_chip->boot_pages); >> + if (ret) { >> + dev_err(dev, "could not retrieve 'amlogic,boot-pages' property: %d", >> + ret); >> + goto err_chip_buf_free; >> + } >> + >> + ret = ofnode_read_u32(node, "amlogic,boot-page-step", >> + &meson_chip->boot_page_step); >> + if (ret) { >> + dev_err(dev, "could not retrieve 'amlogic,boot-page-step' property: %d", >> + ret); >> + goto err_chip_buf_free; >> + } >> + } >> + >> ret = nand_register(0, mtd); >> if (ret) { >> dev_err(dev, "'nand_register()' failed: %d\n", ret); >> -- >> 2.30.1 >> > >