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
>>
> 
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.