@@ -157,6 +157,17 @@
#define NFC_MAX_CS 7
+/*
+ * On A10/A23, this is the size of the NDFC User Data Register, containing the
+ * mandatory user data bytes following the ECC for each ECC step.
+ * Thus, for each ECC step, we need the ECC bytes + USER_DATA_SZ.
+ * Those bits are currently unsused, and kept as default value 0xffffffff.
+ *
+ * On H6/H616, this size became configurable, from 0 bytes to 32, via the
+ * USER_DATA_LEN registers.
+ */
+#define USER_DATA_SZ 4
+
/**
* struct sunxi_nand_chip_sel - stores information related to NAND Chip Select
*
@@ -729,7 +740,7 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
bool bbm, int page)
{
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
- u8 user_data[4];
+ u8 user_data[USER_DATA_SZ];
/* Randomize the Bad Block Marker. */
if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) {
@@ -781,7 +792,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob,
memset(data, pattern, ecc->size);
if (oob)
- memset(oob, pattern, ecc->bytes + 4);
+ memset(oob, pattern, ecc->bytes + USER_DATA_SZ);
return 0;
}
@@ -826,7 +837,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
if (ret)
return ret;
- *cur_off = oob_off + ecc->bytes + 4;
+ *cur_off = oob_off + ecc->bytes + USER_DATA_SZ;
ret = sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, 0,
readl(nfc->regs + NFC_REG_ECC_ST),
@@ -846,11 +857,11 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE,
ecc->size);
- nand_change_read_column_op(nand, oob_off, oob, ecc->bytes + 4,
- false);
+ nand_change_read_column_op(nand, oob_off, oob,
+ ecc->bytes + USER_DATA_SZ, false);
- ret = nand_check_erased_ecc_chunk(data, ecc->size,
- oob, ecc->bytes + 4,
+ ret = nand_check_erased_ecc_chunk(data, ecc->size, oob,
+ ecc->bytes + USER_DATA_SZ,
NULL, 0, ecc->strength);
if (ret >= 0)
raw_mode = 1;
@@ -860,7 +871,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
if (oob_required) {
nand_change_read_column_op(nand, oob_off, NULL, 0,
false);
- sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + 4,
+ sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + USER_DATA_SZ,
true, page);
sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, 0,
@@ -954,7 +965,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
for (i = 0; i < nchunks; i++) {
int data_off = i * ecc->size;
- int oob_off = i * (ecc->bytes + 4);
+ int oob_off = i * (ecc->bytes + USER_DATA_SZ);
u8 *data = buf + data_off;
u8 *oob = nand->oob_poi + oob_off;
bool erased;
@@ -971,7 +982,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
/* TODO: use DMA to retrieve OOB */
nand_change_read_column_op(nand,
mtd->writesize + oob_off,
- oob, ecc->bytes + 4, false);
+ oob, ecc->bytes + USER_DATA_SZ, false);
sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i,
!i, page);
@@ -986,7 +997,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
if (status & NFC_ECC_ERR_MSK) {
for (i = 0; i < nchunks; i++) {
int data_off = i * ecc->size;
- int oob_off = i * (ecc->bytes + 4);
+ int oob_off = i * (ecc->bytes + USER_DATA_SZ);
u8 *data = buf + data_off;
u8 *oob = nand->oob_poi + oob_off;
@@ -1006,10 +1017,10 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
/* TODO: use DMA to retrieve OOB */
nand_change_read_column_op(nand,
mtd->writesize + oob_off,
- oob, ecc->bytes + 4, false);
+ oob, ecc->bytes + USER_DATA_SZ, false);
- ret = nand_check_erased_ecc_chunk(data, ecc->size,
- oob, ecc->bytes + 4,
+ ret = nand_check_erased_ecc_chunk(data, ecc->size, oob,
+ ecc->bytes + USER_DATA_SZ,
NULL, 0,
ecc->strength);
if (ret >= 0)
@@ -1062,7 +1073,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
if (ret)
return ret;
- *cur_off = oob_off + ecc->bytes + 4;
+ *cur_off = oob_off + ecc->bytes + USER_DATA_SZ;
return 0;
}
@@ -1073,7 +1084,7 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand,
{
struct mtd_info *mtd = nand_to_mtd(nand);
struct nand_ecc_ctrl *ecc = &nand->ecc;
- int offset = ((ecc->bytes + 4) * ecc->steps);
+ int offset = ((ecc->bytes + USER_DATA_SZ) * ecc->steps);
int len = mtd->oobsize - offset;
if (len <= 0)
@@ -1106,7 +1117,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf,
for (i = 0; i < ecc->steps; i++) {
int data_off = i * ecc->size;
- int oob_off = i * (ecc->bytes + 4);
+ int oob_off = i * (ecc->bytes + USER_DATA_SZ);
u8 *data = buf + data_off;
u8 *oob = nand->oob_poi + oob_off;
@@ -1165,7 +1176,7 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand,
for (i = data_offs / ecc->size;
i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
int data_off = i * ecc->size;
- int oob_off = i * (ecc->bytes + 4);
+ int oob_off = i * (ecc->bytes + USER_DATA_SZ);
u8 *data = bufpoi + data_off;
u8 *oob = nand->oob_poi + oob_off;
@@ -1219,7 +1230,7 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand,
for (i = 0; i < ecc->steps; i++) {
int data_off = i * ecc->size;
- int oob_off = i * (ecc->bytes + 4);
+ int oob_off = i * (ecc->bytes + USER_DATA_SZ);
const u8 *data = buf + data_off;
const u8 *oob = nand->oob_poi + oob_off;
@@ -1257,7 +1268,7 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand,
for (i = data_offs / ecc->size;
i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) {
int data_off = i * ecc->size;
- int oob_off = i * (ecc->bytes + 4);
+ int oob_off = i * (ecc->bytes + USER_DATA_SZ);
const u8 *data = buf + data_off;
const u8 *oob = nand->oob_poi + oob_off;
@@ -1296,7 +1307,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
goto pio_fallback;
for (i = 0; i < ecc->steps; i++) {
- const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4));
+ const u8 *oob = nand->oob_poi + (i * (ecc->bytes + USER_DATA_SZ));
sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page);
}
@@ -1566,7 +1577,7 @@ static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
if (section >= ecc->steps)
return -ERANGE;
- oobregion->offset = section * (ecc->bytes + 4) + 4;
+ oobregion->offset = section * (ecc->bytes + USER_DATA_SZ) + 4;
oobregion->length = ecc->bytes;
return 0;
@@ -1600,10 +1611,10 @@ static int sunxi_nand_ooblayout_free(struct mtd_info *mtd, int section,
if (section == ecc->steps && ecc->engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST)
return -ERANGE;
- oobregion->offset = section * (ecc->bytes + 4);
+ oobregion->offset = section * (ecc->bytes + USER_DATA_SZ);
if (section < ecc->steps)
- oobregion->length = 4;
+ oobregion->length = USER_DATA_SZ;
else
oobregion->length = mtd->oobsize - oobregion->offset;
@@ -1637,7 +1648,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
bytes = (mtd->oobsize - 2) / nsectors;
/* 4 non-ECC bytes are added before each ECC bytes section */
- bytes -= 4;
+ bytes -= USER_DATA_SZ;
/* and bytes has to be even. */
if (bytes % 2)
@@ -1690,7 +1701,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
nsectors = mtd->writesize / ecc->size;
- if (mtd->oobsize < ((ecc->bytes + 4) * nsectors))
+ if (mtd->oobsize < ((ecc->bytes + USER_DATA_SZ) * nsectors))
return -EINVAL;
ecc->read_oob = sunxi_nfc_hw_ecc_read_oob;