[PATCH v1] mtd: nand: raw: rockchip_nfc: copy hwecc PA data to oob_poi buffer

Rockchip boot blocks are written per 4 x 512 byte sectors per page. Each page must have a page address (PA) pointer in OOB to the next page. Pages are written in a pattern depending on the NAND chip ID. This logic used to build a page pattern table is not fully disclosed and is not easy to fit in the MTD framework. The formula in rk_nfc_write_page_hwecc() function is not correct. Make hwecc and raw behavior identical. Generate boot block page address and pattern for hwecc in user space and copy PA data to/from the already reserved last 4 bytes before EEC in the chip->oob_poi data layout.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/mtd/nand/raw/rockchip_nfc.c | 34 ++++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/drivers/mtd/nand/raw/rockchip_nfc.c b/drivers/mtd/nand/raw/rockchip_nfc.c index 5fcf6a6b..274489ec 100644 --- a/drivers/mtd/nand/raw/rockchip_nfc.c +++ b/drivers/mtd/nand/raw/rockchip_nfc.c @@ -525,7 +525,7 @@ static int rk_nfc_write_page_hwecc(struct mtd_info *mtd, int pages_per_blk = mtd->erasesize / mtd->writesize; int ret = 0, i, boot_rom_mode = 0; dma_addr_t dma_data, dma_oob; - u32 reg; + u32 tmp; u8 *oob;
nand_prog_page_begin_op(chip, page, 0, NULL, 0); @@ -552,6 +552,13 @@ static int rk_nfc_write_page_hwecc(struct mtd_info *mtd, * * 0xFF 0xFF 0xFF 0xFF | BBM OOB1 OOB2 OOB3 | ... * + * The code here just swaps the first 4 bytes with the last + * 4 bytes without losing any data. + * + * The chip->oob_poi data layout: + * + * BBM OOB1 OOB2 OOB3 |......| PA0 PA1 PA2 PA3 + * * Configure the ECC algorithm supported by the boot ROM. */ if (page < (pages_per_blk * rknand->boot_blks)) { @@ -561,21 +568,17 @@ static int rk_nfc_write_page_hwecc(struct mtd_info *mtd, }
for (i = 0; i < ecc->steps; i++) { - if (!i) { - reg = 0xFFFFFFFF; - } else { + if (!i) + oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE; + else oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; - reg = oob[0] | oob[1] << 8 | oob[2] << 16 | - oob[3] << 24; - }
- if (!i && boot_rom_mode) - reg = (page & (pages_per_blk - 1)) * 4; + tmp = oob[0] | oob[1] << 8 | oob[2] << 16 | oob[3] << 24;
if (nfc->cfg->type == NFC_V9) - nfc->oob_buf[i] = reg; + nfc->oob_buf[i] = tmp; else - nfc->oob_buf[i * (oob_step / 4)] = reg; + nfc->oob_buf[i * (oob_step / 4)] = tmp; }
dma_data = dma_map_single((void *)nfc->page_buf, @@ -720,12 +723,17 @@ static int rk_nfc_read_page_hwecc(struct mtd_info *mtd, goto timeout_err; }
- for (i = 1; i < ecc->steps; i++) { - oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; + for (i = 0; i < ecc->steps; i++) { + if (!i) + oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE; + else + oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; + if (nfc->cfg->type == NFC_V9) tmp = nfc->oob_buf[i]; else tmp = nfc->oob_buf[i * (oob_step / 4)]; + *oob++ = (u8)tmp; *oob++ = (u8)(tmp >> 8); *oob++ = (u8)(tmp >> 16); -- 2.30.2

On 2023/6/22 21:59, Johan Jonker wrote:
Rockchip boot blocks are written per 4 x 512 byte sectors per page. Each page must have a page address (PA) pointer in OOB to the next page. Pages are written in a pattern depending on the NAND chip ID. This logic used to build a page pattern table is not fully disclosed and is not easy to fit in the MTD framework. The formula in rk_nfc_write_page_hwecc() function is not correct. Make hwecc and raw behavior identical. Generate boot block page address and pattern for hwecc in user space and copy PA data to/from the already reserved last 4 bytes before EEC in the chip->oob_poi data layout.
Signed-off-by: Johan Jonker jbx6244@gmail.com
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/mtd/nand/raw/rockchip_nfc.c | 34 ++++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/drivers/mtd/nand/raw/rockchip_nfc.c b/drivers/mtd/nand/raw/rockchip_nfc.c index 5fcf6a6b..274489ec 100644 --- a/drivers/mtd/nand/raw/rockchip_nfc.c +++ b/drivers/mtd/nand/raw/rockchip_nfc.c @@ -525,7 +525,7 @@ static int rk_nfc_write_page_hwecc(struct mtd_info *mtd, int pages_per_blk = mtd->erasesize / mtd->writesize; int ret = 0, i, boot_rom_mode = 0; dma_addr_t dma_data, dma_oob;
- u32 reg;
u32 tmp; u8 *oob;
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
@@ -552,6 +552,13 @@ static int rk_nfc_write_page_hwecc(struct mtd_info *mtd, * * 0xFF 0xFF 0xFF 0xFF | BBM OOB1 OOB2 OOB3 | ... *
* The code here just swaps the first 4 bytes with the last
* 4 bytes without losing any data.
*
* The chip->oob_poi data layout:
*
* BBM OOB1 OOB2 OOB3 |......| PA0 PA1 PA2 PA3
*
*/ if (page < (pages_per_blk * rknand->boot_blks)) {
- Configure the ECC algorithm supported by the boot ROM.
@@ -561,21 +568,17 @@ static int rk_nfc_write_page_hwecc(struct mtd_info *mtd, }
for (i = 0; i < ecc->steps; i++) {
if (!i) {
reg = 0xFFFFFFFF;
} else {
if (!i)
oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
else oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
reg = oob[0] | oob[1] << 8 | oob[2] << 16 |
oob[3] << 24;
}
if (!i && boot_rom_mode)
reg = (page & (pages_per_blk - 1)) * 4;
tmp = oob[0] | oob[1] << 8 | oob[2] << 16 | oob[3] << 24;
if (nfc->cfg->type == NFC_V9)
nfc->oob_buf[i] = reg;
elsenfc->oob_buf[i] = tmp;
nfc->oob_buf[i * (oob_step / 4)] = reg;
nfc->oob_buf[i * (oob_step / 4)] = tmp;
}
dma_data = dma_map_single((void *)nfc->page_buf,
@@ -720,12 +723,17 @@ static int rk_nfc_read_page_hwecc(struct mtd_info *mtd, goto timeout_err; }
- for (i = 1; i < ecc->steps; i++) {
oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
- for (i = 0; i < ecc->steps; i++) {
if (!i)
oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
else
oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
- if (nfc->cfg->type == NFC_V9) tmp = nfc->oob_buf[i]; else tmp = nfc->oob_buf[i * (oob_step / 4)];
- *oob++ = (u8)tmp; *oob++ = (u8)(tmp >> 8); *oob++ = (u8)(tmp >> 16);
-- 2.30.2
participants (2)
-
Johan Jonker
-
Kever Yang