@@ -663,7 +663,7 @@ static void sunxi_nfc_select_chip(struct nand_chip *nand, unsigned int cs)
writel(ctl, nfc->regs + NFC_REG_CTL);
}
-static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len)
+static int sunxi_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
{
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
@@ -679,7 +679,7 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len)
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
if (ret)
- break;
+ return ret;
writel(cnt, nfc->regs + NFC_REG_CNT);
tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
@@ -691,17 +691,19 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len)
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
if (ret)
- break;
+ return ret;
if (buf)
memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE,
cnt);
offs += cnt;
}
+
+ return 0;
}
-static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf,
- int len)
+static int sunxi_nfc_write_buf(struct nand_chip *nand, const u8 *buf,
+ int len)
{
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
@@ -717,7 +719,7 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf,
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
if (ret)
- break;
+ return ret;
writel(cnt, nfc->regs + NFC_REG_CNT);
memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt);
@@ -731,10 +733,12 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf,
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
if (ret)
- break;
+ return ret;
offs += cnt;
}
+
+ return 0;
}
/* These seed values have been extracted from Allwinner's BSP */
@@ -884,23 +888,31 @@ static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *bbm)
bbm[1] ^= sunxi_nfc_randomizer_step(state, 8);
}
-static void sunxi_nfc_randomizer_write_buf(struct nand_chip *nand,
- const uint8_t *buf, int len,
- bool ecc, int page)
+static int sunxi_nfc_randomizer_write_buf(struct nand_chip *nand,
+ const u8 *buf, int len,
+ bool ecc, int page)
{
+ int ret;
+
sunxi_nfc_randomizer_config(nand, page, ecc);
sunxi_nfc_randomizer_enable(nand);
- sunxi_nfc_write_buf(nand, buf, len);
+ ret = sunxi_nfc_write_buf(nand, buf, len);
sunxi_nfc_randomizer_disable(nand);
+
+ return ret;
}
-static void sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, uint8_t *buf,
- int len, bool ecc, int page)
+static int sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, u8 *buf,
+ int len, bool ecc, int page)
{
+ int ret;
+
sunxi_nfc_randomizer_config(nand, page, ecc);
sunxi_nfc_randomizer_enable(nand);
- sunxi_nfc_read_buf(nand, buf, len);
+ ret = sunxi_nfc_read_buf(nand, buf, len);
sunxi_nfc_randomizer_disable(nand);
+
+ return ret;
}
static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand)
@@ -1150,31 +1162,39 @@ static int sunxi_get_ecc_offset(struct sunxi_nand_chip *sunxi_nand,
sunxi_nfc_user_data_sz(sunxi_nand, step);
}
-static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand,
- u8 *oob, int *cur_off,
- bool randomize, int page)
+static int sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand,
+ u8 *oob, int *cur_off,
+ bool randomize, int page)
{
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct mtd_info *mtd = nand_to_mtd(nand);
struct nand_ecc_ctrl *ecc = &nand->ecc;
int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps);
int len = mtd->oobsize - offset;
+ int ret;
if (len <= 0)
- return;
+ return 0;
- if (!cur_off || *cur_off != (offset + mtd->writesize))
- nand_change_read_column_op(nand, mtd->writesize + offset,
- NULL, 0, false);
+ if (!cur_off || *cur_off != (offset + mtd->writesize)) {
+ ret = nand_change_read_column_op(nand, mtd->writesize + offset,
+ NULL, 0, false);
+ if (ret)
+ return ret;
+ }
if (!randomize)
- sunxi_nfc_read_buf(nand, oob + offset, len);
+ ret = sunxi_nfc_read_buf(nand, oob + offset, len);
else
- sunxi_nfc_randomizer_read_buf(nand, oob + offset, len,
- false, page);
+ ret = sunxi_nfc_randomizer_read_buf(nand, oob + offset, len,
+ false, page);
+ if (ret)
+ return ret;
if (cur_off)
*cur_off = mtd->oobsize + mtd->writesize;
+
+ return 0;
}
/* Interpret one PIO step or a completed DMA batch before reusing its status. */
@@ -1222,15 +1242,19 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand,
if (read->oob_required) {
/* Keep the existing PIO and DMA representations of parity. */
- nand_change_read_column_op(nand, mtd->writesize + oob_off,
- read->dma ? oob : NULL,
- read->dma ? ecc->bytes + user_data_sz : 0,
- false);
+ ret = nand_change_read_column_op(nand, mtd->writesize + oob_off,
+ read->dma ? oob : NULL,
+ read->dma ? ecc->bytes + user_data_sz : 0,
+ false);
+ if (ret)
+ return ret;
if (!read->dma) {
- sunxi_nfc_randomizer_read_buf(nand, oob,
- ecc->bytes + user_data_sz,
- true, read->page);
+ ret = sunxi_nfc_randomizer_read_buf(nand, oob,
+ ecc->bytes + user_data_sz,
+ true, read->page);
+ if (ret)
+ return ret;
}
sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !step,
@@ -1270,9 +1294,14 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand,
static int sunxi_nfc_oob_finish_read(struct nand_chip *nand,
struct sunxi_nfc_ecc_read *read, int *cur_off)
{
- if (read->oob_required)
- sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, cur_off,
- !read->has_erased_chunk, read->page);
+ int ret;
+
+ if (read->oob_required) {
+ ret = sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, cur_off,
+ !read->has_erased_chunk, read->page);
+ if (ret)
+ return ret;
+ }
return read->max_bitflips;
}
@@ -1291,13 +1320,21 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
u32 pattern_found;
int ret;
- if (*cur_off != data_off)
- nand_change_read_column_op(nand, data_off, NULL, 0, false);
+ if (*cur_off != data_off) {
+ ret = nand_change_read_column_op(nand, data_off, NULL, 0, false);
+ if (ret)
+ return ret;
+ }
- sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page);
+ ret = sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page);
+ if (ret)
+ return ret;
- if (data_off + ecc->size != oob_off)
- nand_change_read_column_op(nand, oob_off, NULL, 0, false);
+ if (data_off + ecc->size != oob_off) {
+ ret = nand_change_read_column_op(nand, oob_off, NULL, 0, false);
+ if (ret)
+ return ret;
+ }
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
if (ret)
@@ -1420,13 +1457,21 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
/* From the controller point of view, we are at step 0 */
const int nfc_step = 0;
- if (data_off != *cur_off)
- nand_change_write_column_op(nand, data_off, NULL, 0, false);
+ if (data_off != *cur_off) {
+ ret = nand_change_write_column_op(nand, data_off, NULL, 0, false);
+ if (ret)
+ return ret;
+ }
- sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page);
+ ret = sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page);
+ if (ret)
+ return ret;
- if (data_off + ecc->size != oob_off)
- nand_change_write_column_op(nand, oob_off, NULL, 0, false);
+ if (data_off + ecc->size != oob_off) {
+ ret = nand_change_write_column_op(nand, oob_off, NULL, 0, false);
+ if (ret)
+ return ret;
+ }
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
if (ret)
@@ -1452,27 +1497,35 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
return 0;
}
-static void sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand,
- u8 *oob, int *cur_off,
- int page)
+static int sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand,
+ u8 *oob, int *cur_off,
+ int page)
{
struct mtd_info *mtd = nand_to_mtd(nand);
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct nand_ecc_ctrl *ecc = &nand->ecc;
int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps);
int len = mtd->oobsize - offset;
+ int ret;
if (len <= 0)
- return;
+ return 0;
- if (!cur_off || *cur_off != offset)
- nand_change_write_column_op(nand, offset + mtd->writesize,
- NULL, 0, false);
+ if (!cur_off || *cur_off != offset) {
+ ret = nand_change_write_column_op(nand, offset + mtd->writesize,
+ NULL, 0, false);
+ if (ret)
+ return ret;
+ }
- sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page);
+ ret = sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page);
+ if (ret)
+ return ret;
if (cur_off)
*cur_off = mtd->oobsize + mtd->writesize;
+
+ return 0;
}
static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf,
@@ -1620,8 +1673,8 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand,
}
if (oob_required || (nand->options & NAND_NEED_SCRAMBLING))
- sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi,
- &cur_off, page);
+ ret = sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi,
+ &cur_off, page);
out:
sunxi_nfc_hw_ecc_disable(nand);
@@ -1746,10 +1799,13 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
if (ret)
return ret;
- if (oob_required || (nand->options & NAND_NEED_SCRAMBLING))
+ if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) {
/* TODO: use DMA to transfer extra OOB bytes ? */
- sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi,
- NULL, page);
+ ret = sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi,
+ NULL, page);
+ if (ret)
+ return ret;
+ }
return nand_prog_page_end_op(nand);