Lines Matching +full:dma +full:- +full:poll +full:- +full:cnt

1 // SPDX-License-Identifier: GPL-2.0+
6 * https://github.com/yuq/sunxi-nfc-mtd
9 * https://github.com/hno/Allwinner-Info
16 #include <linux/dma-mapping.h>
70 #define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
107 #define NFC_ADR_NUM(x) (((x) - 1) << 16)
161 * struct sunxi_nand_chip_sel - stores information related to NAND Chip Select
164 * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the NFC
172 * struct sunxi_nand_hw_ecc - stores information related to HW ECC support
181 * struct sunxi_nand_chip - stores NAND chip device related information
212 * @has_mdma: Use mbus dma mode, otherwise general dma
215 * @dma_maxburst: DMA maxburst
224 * struct sunxi_nfc - stores sunxi NAND controller information
237 * @dmac: the DMA channel attached to the NAND controller
263 u32 st = readl(nfc->regs + NFC_REG_ST); in sunxi_nfc_interrupt()
264 u32 ien = readl(nfc->regs + NFC_REG_INT); in sunxi_nfc_interrupt()
270 complete(&nfc->complete); in sunxi_nfc_interrupt()
272 writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST); in sunxi_nfc_interrupt()
273 writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT); in sunxi_nfc_interrupt()
284 return -EINVAL; in sunxi_nfc_wait_events()
290 init_completion(&nfc->complete); in sunxi_nfc_wait_events()
292 writel(events, nfc->regs + NFC_REG_INT); in sunxi_nfc_wait_events()
294 ret = wait_for_completion_timeout(&nfc->complete, in sunxi_nfc_wait_events()
297 ret = -ETIMEDOUT; in sunxi_nfc_wait_events()
301 writel(0, nfc->regs + NFC_REG_INT); in sunxi_nfc_wait_events()
305 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status, in sunxi_nfc_wait_events()
310 writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST); in sunxi_nfc_wait_events()
313 dev_err(nfc->dev, "wait interrupt timedout\n"); in sunxi_nfc_wait_events()
323 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status, in sunxi_nfc_wait_cmd_fifo_empty()
327 dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n"); in sunxi_nfc_wait_cmd_fifo_empty()
337 writel(0, nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_rst()
338 writel(NFC_RESET, nfc->regs + NFC_REG_CTL); in sunxi_nfc_rst()
340 ret = readl_poll_timeout(nfc->regs + NFC_REG_CTL, ctl, in sunxi_nfc_rst()
344 dev_err(nfc->dev, "wait for NAND controller reset timedout\n"); in sunxi_nfc_rst()
365 ret = dma_map_sg(nfc->dev, sg, 1, ddir); in sunxi_nfc_dma_op_prepare()
367 return -ENOMEM; in sunxi_nfc_dma_op_prepare()
369 if (!nfc->caps->has_mdma) { in sunxi_nfc_dma_op_prepare()
370 dmad = dmaengine_prep_slave_sg(nfc->dmac, sg, 1, tdir, DMA_CTRL_ACK); in sunxi_nfc_dma_op_prepare()
372 ret = -EINVAL; in sunxi_nfc_dma_op_prepare()
377 writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD, in sunxi_nfc_dma_op_prepare()
378 nfc->regs + NFC_REG_CTL); in sunxi_nfc_dma_op_prepare()
379 writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM); in sunxi_nfc_dma_op_prepare()
380 writel(chunksize, nfc->regs + NFC_REG_CNT); in sunxi_nfc_dma_op_prepare()
382 if (nfc->caps->has_mdma) { in sunxi_nfc_dma_op_prepare()
383 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_DMA_TYPE_NORMAL, in sunxi_nfc_dma_op_prepare()
384 nfc->regs + NFC_REG_CTL); in sunxi_nfc_dma_op_prepare()
385 writel(chunksize * nchunks, nfc->regs + NFC_REG_MDMA_CNT); in sunxi_nfc_dma_op_prepare()
386 writel(sg_dma_address(sg), nfc->regs + NFC_REG_MDMA_ADDR); in sunxi_nfc_dma_op_prepare()
398 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD, in sunxi_nfc_dma_op_prepare()
399 nfc->regs + NFC_REG_CTL); in sunxi_nfc_dma_op_prepare()
402 dma_unmap_sg(nfc->dev, sg, 1, ddir); in sunxi_nfc_dma_op_prepare()
410 dma_unmap_sg(nfc->dev, sg, 1, ddir); in sunxi_nfc_dma_op_cleanup()
411 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD, in sunxi_nfc_dma_op_cleanup()
412 nfc->regs + NFC_REG_CTL); in sunxi_nfc_dma_op_cleanup()
419 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); in sunxi_nfc_select_chip()
423 if (cs >= sunxi_nand->nsels) in sunxi_nfc_select_chip()
426 ctl = readl(nfc->regs + NFC_REG_CTL) & in sunxi_nfc_select_chip()
429 sel = &sunxi_nand->sels[cs]; in sunxi_nfc_select_chip()
430 ctl |= NFC_CE_SEL(sel->cs) | NFC_EN | NFC_PAGE_SHIFT(nand->page_shift); in sunxi_nfc_select_chip()
431 if (sel->rb >= 0) in sunxi_nfc_select_chip()
432 ctl |= NFC_RB_SEL(sel->rb); in sunxi_nfc_select_chip()
434 writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA); in sunxi_nfc_select_chip()
436 if (nfc->clk_rate != sunxi_nand->clk_rate) { in sunxi_nfc_select_chip()
437 clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate); in sunxi_nfc_select_chip()
438 nfc->clk_rate = sunxi_nand->clk_rate; in sunxi_nfc_select_chip()
441 writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL); in sunxi_nfc_select_chip()
442 writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG); in sunxi_nfc_select_chip()
443 writel(ctl, nfc->regs + NFC_REG_CTL); in sunxi_nfc_select_chip()
449 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); in sunxi_nfc_read_buf()
451 int cnt; in sunxi_nfc_read_buf() local
456 bool poll = false; in sunxi_nfc_read_buf() local
458 cnt = min(len - offs, NFC_SRAM_SIZE); in sunxi_nfc_read_buf()
464 writel(cnt, nfc->regs + NFC_REG_CNT); in sunxi_nfc_read_buf()
466 writel(tmp, nfc->regs + NFC_REG_CMD); in sunxi_nfc_read_buf()
469 if (cnt < 64) in sunxi_nfc_read_buf()
470 poll = true; in sunxi_nfc_read_buf()
472 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); in sunxi_nfc_read_buf()
477 memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE, in sunxi_nfc_read_buf()
478 cnt); in sunxi_nfc_read_buf()
479 offs += cnt; in sunxi_nfc_read_buf()
487 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); in sunxi_nfc_write_buf()
489 int cnt; in sunxi_nfc_write_buf() local
494 bool poll = false; in sunxi_nfc_write_buf() local
496 cnt = min(len - offs, NFC_SRAM_SIZE); in sunxi_nfc_write_buf()
502 writel(cnt, nfc->regs + NFC_REG_CNT); in sunxi_nfc_write_buf()
503 memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt); in sunxi_nfc_write_buf()
506 writel(tmp, nfc->regs + NFC_REG_CMD); in sunxi_nfc_write_buf()
509 if (cnt < 64) in sunxi_nfc_write_buf()
510 poll = true; in sunxi_nfc_write_buf()
512 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); in sunxi_nfc_write_buf()
516 offs += cnt; in sunxi_nfc_write_buf()
595 while (count--) in sunxi_nfc_randomizer_step()
607 int mod = mtd_div_by_ws(mtd->erasesize, mtd); in sunxi_nfc_randomizer_state()
613 if (mtd->ecc_step_size == 512) in sunxi_nfc_randomizer_state()
625 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_randomizer_config()
626 u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_config()
629 if (!(nand->options & NAND_NEED_SCRAMBLING)) in sunxi_nfc_randomizer_config()
632 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_config()
634 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK; in sunxi_nfc_randomizer_config()
635 writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_config()
640 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_randomizer_enable()
642 if (!(nand->options & NAND_NEED_SCRAMBLING)) in sunxi_nfc_randomizer_enable()
645 writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN, in sunxi_nfc_randomizer_enable()
646 nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_enable()
651 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_randomizer_disable()
653 if (!(nand->options & NAND_NEED_SCRAMBLING)) in sunxi_nfc_randomizer_disable()
656 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN, in sunxi_nfc_randomizer_disable()
657 nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_disable()
690 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_enable()
692 writel(sunxi_nand->ecc.ecc_ctl, nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_hw_ecc_enable()
697 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_disable()
699 writel(0, nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_hw_ecc_disable()
718 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_get_prot_oob_bytes()
720 sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)), in sunxi_nfc_hw_ecc_get_prot_oob_bytes()
723 /* De-randomize the Bad Block Marker. */ in sunxi_nfc_hw_ecc_get_prot_oob_bytes()
724 if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) in sunxi_nfc_hw_ecc_get_prot_oob_bytes()
732 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_set_prot_oob_bytes()
736 if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { in sunxi_nfc_hw_ecc_set_prot_oob_bytes()
743 nfc->regs + NFC_REG_USER_DATA(step)); in sunxi_nfc_hw_ecc_set_prot_oob_bytes()
752 mtd->ecc_stats.failed++; in sunxi_nfc_hw_ecc_update_stats()
754 mtd->ecc_stats.corrected += ret; in sunxi_nfc_hw_ecc_update_stats()
762 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_correct()
763 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_correct()
769 return -EBADMSG; in sunxi_nfc_hw_ecc_correct()
774 if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) { in sunxi_nfc_hw_ecc_correct()
782 memset(data, pattern, ecc->size); in sunxi_nfc_hw_ecc_correct()
785 memset(oob, pattern, ecc->bytes + 4); in sunxi_nfc_hw_ecc_correct()
790 tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step)); in sunxi_nfc_hw_ecc_correct()
802 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_read_chunk()
803 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_chunk()
811 sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); in sunxi_nfc_hw_ecc_read_chunk()
813 if (data_off + ecc->size != oob_off) in sunxi_nfc_hw_ecc_read_chunk()
822 nfc->regs + NFC_REG_CMD); in sunxi_nfc_hw_ecc_read_chunk()
829 *cur_off = oob_off + ecc->bytes + 4; in sunxi_nfc_hw_ecc_read_chunk()
832 readl(nfc->regs + NFC_REG_ECC_ST), in sunxi_nfc_hw_ecc_read_chunk()
839 * Re-read the data with the randomizer disabled to identify in sunxi_nfc_hw_ecc_read_chunk()
842 if (nand->options & NAND_NEED_SCRAMBLING) in sunxi_nfc_hw_ecc_read_chunk()
844 ecc->size, false); in sunxi_nfc_hw_ecc_read_chunk()
846 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, in sunxi_nfc_hw_ecc_read_chunk()
847 ecc->size); in sunxi_nfc_hw_ecc_read_chunk()
849 nand_change_read_column_op(nand, oob_off, oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
852 ret = nand_check_erased_ecc_chunk(data, ecc->size, in sunxi_nfc_hw_ecc_read_chunk()
853 oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
854 NULL, 0, ecc->strength); in sunxi_nfc_hw_ecc_read_chunk()
858 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); in sunxi_nfc_hw_ecc_read_chunk()
863 sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
881 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_extra_oob()
882 int offset = ((ecc->bytes + 4) * ecc->steps); in sunxi_nfc_hw_ecc_read_extra_oob()
883 int len = mtd->oobsize - offset; in sunxi_nfc_hw_ecc_read_extra_oob()
889 nand_change_read_column_op(nand, mtd->writesize, NULL, 0, in sunxi_nfc_hw_ecc_read_extra_oob()
899 *cur_off = mtd->oobsize + mtd->writesize; in sunxi_nfc_hw_ecc_read_extra_oob()
906 bool randomized = nand->options & NAND_NEED_SCRAMBLING; in sunxi_nfc_hw_ecc_read_chunks_dma()
907 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_read_chunks_dma()
909 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_chunks_dma()
919 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks, in sunxi_nfc_hw_ecc_read_chunks_dma()
929 NAND_CMD_READSTART, nfc->regs + NFC_REG_RCMD_SET); in sunxi_nfc_hw_ecc_read_chunks_dma()
933 if (nfc->caps->has_mdma) in sunxi_nfc_hw_ecc_read_chunks_dma()
936 dma_async_issue_pending(nfc->dmac); in sunxi_nfc_hw_ecc_read_chunks_dma()
939 nfc->regs + NFC_REG_CMD); in sunxi_nfc_hw_ecc_read_chunks_dma()
942 if (ret && !nfc->caps->has_mdma) in sunxi_nfc_hw_ecc_read_chunks_dma()
943 dmaengine_terminate_all(nfc->dmac); in sunxi_nfc_hw_ecc_read_chunks_dma()
953 status = readl(nfc->regs + NFC_REG_ECC_ST); in sunxi_nfc_hw_ecc_read_chunks_dma()
956 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_chunks_dma()
957 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_chunks_dma()
959 u8 *oob = nand->oob_poi + oob_off; in sunxi_nfc_hw_ecc_read_chunks_dma()
971 /* TODO: use DMA to retrieve OOB */ in sunxi_nfc_hw_ecc_read_chunks_dma()
973 mtd->writesize + oob_off, in sunxi_nfc_hw_ecc_read_chunks_dma()
974 oob, ecc->bytes + 4, false); in sunxi_nfc_hw_ecc_read_chunks_dma()
988 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_chunks_dma()
989 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_chunks_dma()
991 u8 *oob = nand->oob_poi + oob_off; in sunxi_nfc_hw_ecc_read_chunks_dma()
997 * Re-read the data with the randomizer disabled to in sunxi_nfc_hw_ecc_read_chunks_dma()
999 * TODO: use DMA to read page in raw mode in sunxi_nfc_hw_ecc_read_chunks_dma()
1003 data, ecc->size, in sunxi_nfc_hw_ecc_read_chunks_dma()
1006 /* TODO: use DMA to retrieve OOB */ in sunxi_nfc_hw_ecc_read_chunks_dma()
1008 mtd->writesize + oob_off, in sunxi_nfc_hw_ecc_read_chunks_dma()
1009 oob, ecc->bytes + 4, false); in sunxi_nfc_hw_ecc_read_chunks_dma()
1011 ret = nand_check_erased_ecc_chunk(data, ecc->size, in sunxi_nfc_hw_ecc_read_chunks_dma()
1012 oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunks_dma()
1014 ecc->strength); in sunxi_nfc_hw_ecc_read_chunks_dma()
1023 sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, in sunxi_nfc_hw_ecc_read_chunks_dma()
1036 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_write_chunk()
1037 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_chunk()
1043 sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); in sunxi_nfc_hw_ecc_write_chunk()
1045 if (data_off + ecc->size != oob_off) in sunxi_nfc_hw_ecc_write_chunk()
1057 nfc->regs + NFC_REG_CMD); in sunxi_nfc_hw_ecc_write_chunk()
1064 *cur_off = oob_off + ecc->bytes + 4; in sunxi_nfc_hw_ecc_write_chunk()
1074 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_extra_oob()
1075 int offset = ((ecc->bytes + 4) * ecc->steps); in sunxi_nfc_hw_ecc_write_extra_oob()
1076 int len = mtd->oobsize - offset; in sunxi_nfc_hw_ecc_write_extra_oob()
1082 nand_change_write_column_op(nand, offset + mtd->writesize, in sunxi_nfc_hw_ecc_write_extra_oob()
1088 *cur_off = mtd->oobsize + mtd->writesize; in sunxi_nfc_hw_ecc_write_extra_oob()
1095 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_page()
1100 sunxi_nfc_select_chip(nand, nand->cur_cs); in sunxi_nfc_hw_ecc_read_page()
1106 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_read_page()
1107 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_page()
1108 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_page()
1110 u8 *oob = nand->oob_poi + oob_off; in sunxi_nfc_hw_ecc_read_page()
1113 oob_off + mtd->writesize, in sunxi_nfc_hw_ecc_read_page()
1123 sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, in sunxi_nfc_hw_ecc_read_page()
1136 sunxi_nfc_select_chip(nand, nand->cur_cs); in sunxi_nfc_hw_ecc_read_page_dma()
1141 nand->ecc.steps); in sunxi_nfc_hw_ecc_read_page_dma()
1154 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_subpage()
1158 sunxi_nfc_select_chip(nand, nand->cur_cs); in sunxi_nfc_hw_ecc_read_subpage()
1164 for (i = data_offs / ecc->size; in sunxi_nfc_hw_ecc_read_subpage()
1165 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { in sunxi_nfc_hw_ecc_read_subpage()
1166 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_subpage()
1167 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_subpage()
1169 u8 *oob = nand->oob_poi + oob_off; in sunxi_nfc_hw_ecc_read_subpage()
1173 oob_off + mtd->writesize, in sunxi_nfc_hw_ecc_read_subpage()
1189 int nchunks = DIV_ROUND_UP(data_offs + readlen, nand->ecc.size); in sunxi_nfc_hw_ecc_read_subpage_dma()
1192 sunxi_nfc_select_chip(nand, nand->cur_cs); in sunxi_nfc_hw_ecc_read_subpage_dma()
1210 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_page()
1213 sunxi_nfc_select_chip(nand, nand->cur_cs); in sunxi_nfc_hw_ecc_write_page()
1219 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_write_page()
1220 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_write_page()
1221 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_write_page()
1223 const u8 *oob = nand->oob_poi + oob_off; in sunxi_nfc_hw_ecc_write_page()
1226 oob_off + mtd->writesize, in sunxi_nfc_hw_ecc_write_page()
1232 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) in sunxi_nfc_hw_ecc_write_page()
1233 sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, in sunxi_nfc_hw_ecc_write_page()
1247 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_subpage()
1250 sunxi_nfc_select_chip(nand, nand->cur_cs); in sunxi_nfc_hw_ecc_write_subpage()
1256 for (i = data_offs / ecc->size; in sunxi_nfc_hw_ecc_write_subpage()
1257 i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) { in sunxi_nfc_hw_ecc_write_subpage()
1258 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_write_subpage()
1259 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_write_subpage()
1261 const u8 *oob = nand->oob_poi + oob_off; in sunxi_nfc_hw_ecc_write_subpage()
1264 oob_off + mtd->writesize, in sunxi_nfc_hw_ecc_write_subpage()
1280 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_write_page_dma()
1281 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_page_dma()
1286 sunxi_nfc_select_chip(nand, nand->cur_cs); in sunxi_nfc_hw_ecc_write_page_dma()
1292 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps, in sunxi_nfc_hw_ecc_write_page_dma()
1297 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_write_page_dma()
1298 const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4)); in sunxi_nfc_hw_ecc_write_page_dma()
1310 nfc->regs + NFC_REG_WCMD_SET); in sunxi_nfc_hw_ecc_write_page_dma()
1314 if (nfc->caps->has_mdma) in sunxi_nfc_hw_ecc_write_page_dma()
1317 dma_async_issue_pending(nfc->dmac); in sunxi_nfc_hw_ecc_write_page_dma()
1321 nfc->regs + NFC_REG_CMD); in sunxi_nfc_hw_ecc_write_page_dma()
1324 if (ret && !nfc->caps->has_mdma) in sunxi_nfc_hw_ecc_write_page_dma()
1325 dmaengine_terminate_all(nfc->dmac); in sunxi_nfc_hw_ecc_write_page_dma()
1335 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) in sunxi_nfc_hw_ecc_write_page_dma()
1336 /* TODO: use DMA to transfer extra OOB bytes ? */ in sunxi_nfc_hw_ecc_write_page_dma()
1337 sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, in sunxi_nfc_hw_ecc_write_page_dma()
1350 return nand->ecc.read_page(nand, buf, 1, page); in sunxi_nfc_hw_ecc_read_oob()
1359 memset(buf, 0xff, mtd->writesize); in sunxi_nfc_hw_ecc_write_oob()
1360 ret = nand->ecc.write_page(nand, buf, 1, page); in sunxi_nfc_hw_ecc_write_oob()
1383 return -EINVAL; in _sunxi_nand_lookup_timing()
1393 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); in sunxi_nfc_setup_interface()
1401 return -ENOTSUPP; in sunxi_nfc_setup_interface()
1404 if (timings->tCLS_min > min_clk_period) in sunxi_nfc_setup_interface()
1405 min_clk_period = timings->tCLS_min; in sunxi_nfc_setup_interface()
1408 if (timings->tCLH_min > min_clk_period) in sunxi_nfc_setup_interface()
1409 min_clk_period = timings->tCLH_min; in sunxi_nfc_setup_interface()
1412 if (timings->tCS_min > min_clk_period) in sunxi_nfc_setup_interface()
1413 min_clk_period = timings->tCS_min; in sunxi_nfc_setup_interface()
1416 if (timings->tCH_min > min_clk_period) in sunxi_nfc_setup_interface()
1417 min_clk_period = timings->tCH_min; in sunxi_nfc_setup_interface()
1420 if (timings->tWP_min > min_clk_period) in sunxi_nfc_setup_interface()
1421 min_clk_period = timings->tWP_min; in sunxi_nfc_setup_interface()
1424 if (timings->tWH_min > min_clk_period) in sunxi_nfc_setup_interface()
1425 min_clk_period = timings->tWH_min; in sunxi_nfc_setup_interface()
1428 if (timings->tALS_min > min_clk_period) in sunxi_nfc_setup_interface()
1429 min_clk_period = timings->tALS_min; in sunxi_nfc_setup_interface()
1432 if (timings->tDS_min > min_clk_period) in sunxi_nfc_setup_interface()
1433 min_clk_period = timings->tDS_min; in sunxi_nfc_setup_interface()
1436 if (timings->tDH_min > min_clk_period) in sunxi_nfc_setup_interface()
1437 min_clk_period = timings->tDH_min; in sunxi_nfc_setup_interface()
1440 if (timings->tRR_min > (min_clk_period * 3)) in sunxi_nfc_setup_interface()
1441 min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3); in sunxi_nfc_setup_interface()
1444 if (timings->tALH_min > min_clk_period) in sunxi_nfc_setup_interface()
1445 min_clk_period = timings->tALH_min; in sunxi_nfc_setup_interface()
1448 if (timings->tRP_min > min_clk_period) in sunxi_nfc_setup_interface()
1449 min_clk_period = timings->tRP_min; in sunxi_nfc_setup_interface()
1452 if (timings->tREH_min > min_clk_period) in sunxi_nfc_setup_interface()
1453 min_clk_period = timings->tREH_min; in sunxi_nfc_setup_interface()
1456 if (timings->tRC_min > (min_clk_period * 2)) in sunxi_nfc_setup_interface()
1457 min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2); in sunxi_nfc_setup_interface()
1460 if (timings->tWC_min > (min_clk_period * 2)) in sunxi_nfc_setup_interface()
1461 min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2); in sunxi_nfc_setup_interface()
1463 /* T16 - T19 + tCAD */ in sunxi_nfc_setup_interface()
1464 if (timings->tWB_max > (min_clk_period * 20)) in sunxi_nfc_setup_interface()
1465 min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20); in sunxi_nfc_setup_interface()
1467 if (timings->tADL_min > (min_clk_period * 32)) in sunxi_nfc_setup_interface()
1468 min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32); in sunxi_nfc_setup_interface()
1470 if (timings->tWHR_min > (min_clk_period * 32)) in sunxi_nfc_setup_interface()
1471 min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32); in sunxi_nfc_setup_interface()
1473 if (timings->tRHW_min > (min_clk_period * 20)) in sunxi_nfc_setup_interface()
1474 min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20); in sunxi_nfc_setup_interface()
1477 * In non-EDO, tREA should be less than tRP to guarantee that the in sunxi_nfc_setup_interface()
1485 * 2/ Use EDO mode (only works if timings->tRLOH > 0) in sunxi_nfc_setup_interface()
1487 if (timings->tREA_max > min_clk_period && !timings->tRLOH_min) in sunxi_nfc_setup_interface()
1488 min_clk_period = timings->tREA_max; in sunxi_nfc_setup_interface()
1490 tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max, in sunxi_nfc_setup_interface()
1493 dev_err(nfc->dev, "unsupported tWB\n"); in sunxi_nfc_setup_interface()
1497 tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3; in sunxi_nfc_setup_interface()
1499 dev_err(nfc->dev, "unsupported tADL\n"); in sunxi_nfc_setup_interface()
1500 return -EINVAL; in sunxi_nfc_setup_interface()
1503 tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3; in sunxi_nfc_setup_interface()
1505 dev_err(nfc->dev, "unsupported tWHR\n"); in sunxi_nfc_setup_interface()
1506 return -EINVAL; in sunxi_nfc_setup_interface()
1509 tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min, in sunxi_nfc_setup_interface()
1512 dev_err(nfc->dev, "unsupported tRHW\n"); in sunxi_nfc_setup_interface()
1526 sunxi_nand->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD); in sunxi_nfc_setup_interface()
1537 sunxi_nand->clk_rate = NSEC_PER_SEC / min_clk_period; in sunxi_nfc_setup_interface()
1538 real_clk_rate = clk_round_rate(nfc->mod_clk, sunxi_nand->clk_rate); in sunxi_nfc_setup_interface()
1540 dev_err(nfc->dev, "Unable to round clk %lu\n", in sunxi_nfc_setup_interface()
1541 sunxi_nand->clk_rate); in sunxi_nfc_setup_interface()
1542 return -EINVAL; in sunxi_nfc_setup_interface()
1545 sunxi_nand->timing_ctl = 0; in sunxi_nfc_setup_interface()
1553 if (min_clk_period * 2 < 30 || min_clk_period * 1000 < timings->tREA_max) in sunxi_nfc_setup_interface()
1554 sunxi_nand->timing_ctl = NFC_TIMING_CTL_EDO; in sunxi_nfc_setup_interface()
1563 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_ooblayout_ecc()
1565 if (section >= ecc->steps) in sunxi_nand_ooblayout_ecc()
1566 return -ERANGE; in sunxi_nand_ooblayout_ecc()
1568 oobregion->offset = section * (ecc->bytes + 4) + 4; in sunxi_nand_ooblayout_ecc()
1569 oobregion->length = ecc->bytes; in sunxi_nand_ooblayout_ecc()
1578 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_ooblayout_free()
1580 if (section > ecc->steps) in sunxi_nand_ooblayout_free()
1581 return -ERANGE; in sunxi_nand_ooblayout_free()
1588 if (!section && ecc->engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) { in sunxi_nand_ooblayout_free()
1589 oobregion->offset = 2; in sunxi_nand_ooblayout_free()
1590 oobregion->length = 2; in sunxi_nand_ooblayout_free()
1599 if (section == ecc->steps && ecc->engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) in sunxi_nand_ooblayout_free()
1600 return -ERANGE; in sunxi_nand_ooblayout_free()
1602 oobregion->offset = section * (ecc->bytes + 4); in sunxi_nand_ooblayout_free()
1604 if (section < ecc->steps) in sunxi_nand_ooblayout_free()
1605 oobregion->length = 4; in sunxi_nand_ooblayout_free()
1607 oobregion->length = mtd->oobsize - oobregion->offset; in sunxi_nand_ooblayout_free()
1623 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nand_hw_ecc_ctrl_init()
1629 if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE_STRENGTH) { in sunxi_nand_hw_ecc_ctrl_init()
1632 ecc->size = 1024; in sunxi_nand_hw_ecc_ctrl_init()
1633 nsectors = mtd->writesize / ecc->size; in sunxi_nand_hw_ecc_ctrl_init()
1636 bytes = (mtd->oobsize - 2) / nsectors; in sunxi_nand_hw_ecc_ctrl_init()
1638 /* 4 non-ECC bytes are added before each ECC bytes section */ in sunxi_nand_hw_ecc_ctrl_init()
1639 bytes -= 4; in sunxi_nand_hw_ecc_ctrl_init()
1643 bytes--; in sunxi_nand_hw_ecc_ctrl_init()
1645 ecc->strength = bytes * 8 / fls(8 * ecc->size); in sunxi_nand_hw_ecc_ctrl_init()
1648 if (strengths[i] > ecc->strength) in sunxi_nand_hw_ecc_ctrl_init()
1653 ecc->strength = 0; in sunxi_nand_hw_ecc_ctrl_init()
1655 ecc->strength = strengths[i - 1]; in sunxi_nand_hw_ecc_ctrl_init()
1658 if (ecc->size != 512 && ecc->size != 1024) in sunxi_nand_hw_ecc_ctrl_init()
1659 return -EINVAL; in sunxi_nand_hw_ecc_ctrl_init()
1662 if (ecc->size == 512 && mtd->writesize > 512) { in sunxi_nand_hw_ecc_ctrl_init()
1663 ecc->size = 1024; in sunxi_nand_hw_ecc_ctrl_init()
1664 ecc->strength *= 2; in sunxi_nand_hw_ecc_ctrl_init()
1669 if (ecc->strength <= strengths[i]) { in sunxi_nand_hw_ecc_ctrl_init()
1671 * Update ecc->strength value with the actual strength in sunxi_nand_hw_ecc_ctrl_init()
1674 ecc->strength = strengths[i]; in sunxi_nand_hw_ecc_ctrl_init()
1680 dev_err(nfc->dev, "unsupported strength\n"); in sunxi_nand_hw_ecc_ctrl_init()
1681 return -ENOTSUPP; in sunxi_nand_hw_ecc_ctrl_init()
1685 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8); in sunxi_nand_hw_ecc_ctrl_init()
1688 ecc->bytes = ALIGN(ecc->bytes, 2); in sunxi_nand_hw_ecc_ctrl_init()
1690 nsectors = mtd->writesize / ecc->size; in sunxi_nand_hw_ecc_ctrl_init()
1692 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) in sunxi_nand_hw_ecc_ctrl_init()
1693 return -EINVAL; in sunxi_nand_hw_ecc_ctrl_init()
1695 ecc->read_oob = sunxi_nfc_hw_ecc_read_oob; in sunxi_nand_hw_ecc_ctrl_init()
1696 ecc->write_oob = sunxi_nfc_hw_ecc_write_oob; in sunxi_nand_hw_ecc_ctrl_init()
1699 if (nfc->dmac || nfc->caps->has_mdma) { in sunxi_nand_hw_ecc_ctrl_init()
1700 ecc->read_page = sunxi_nfc_hw_ecc_read_page_dma; in sunxi_nand_hw_ecc_ctrl_init()
1701 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage_dma; in sunxi_nand_hw_ecc_ctrl_init()
1702 ecc->write_page = sunxi_nfc_hw_ecc_write_page_dma; in sunxi_nand_hw_ecc_ctrl_init()
1703 nand->options |= NAND_USES_DMA; in sunxi_nand_hw_ecc_ctrl_init()
1705 ecc->read_page = sunxi_nfc_hw_ecc_read_page; in sunxi_nand_hw_ecc_ctrl_init()
1706 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage; in sunxi_nand_hw_ecc_ctrl_init()
1707 ecc->write_page = sunxi_nfc_hw_ecc_write_page; in sunxi_nand_hw_ecc_ctrl_init()
1710 /* TODO: support DMA for raw accesses and subpage write */ in sunxi_nand_hw_ecc_ctrl_init()
1711 ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage; in sunxi_nand_hw_ecc_ctrl_init()
1712 ecc->read_oob_raw = nand_read_oob_std; in sunxi_nand_hw_ecc_ctrl_init()
1713 ecc->write_oob_raw = nand_write_oob_std; in sunxi_nand_hw_ecc_ctrl_init()
1715 sunxi_nand->ecc.ecc_ctl = NFC_ECC_MODE(i) | NFC_ECC_EXCEPTION | in sunxi_nand_hw_ecc_ctrl_init()
1718 if (ecc->size == 512) in sunxi_nand_hw_ecc_ctrl_init()
1719 sunxi_nand->ecc.ecc_ctl |= NFC_ECC_BLOCK_512; in sunxi_nand_hw_ecc_ctrl_init()
1727 nanddev_get_ecc_requirements(&nand->base); in sunxi_nand_attach_chip()
1728 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_attach_chip()
1732 if (nand->bbt_options & NAND_BBT_USE_FLASH) in sunxi_nand_attach_chip()
1733 nand->bbt_options |= NAND_BBT_NO_OOB; in sunxi_nand_attach_chip()
1735 if (nand->options & NAND_NEED_SCRAMBLING) in sunxi_nand_attach_chip()
1736 nand->options |= NAND_NO_SUBPAGE_WRITE; in sunxi_nand_attach_chip()
1738 nand->options |= NAND_SUBPAGE_READ; in sunxi_nand_attach_chip()
1740 if (!ecc->size) { in sunxi_nand_attach_chip()
1741 ecc->size = requirements->step_size; in sunxi_nand_attach_chip()
1742 ecc->strength = requirements->strength; in sunxi_nand_attach_chip()
1745 if (!ecc->size || !ecc->strength) in sunxi_nand_attach_chip()
1746 return -EINVAL; in sunxi_nand_attach_chip()
1748 switch (ecc->engine_type) { in sunxi_nand_attach_chip()
1758 return -EINVAL; in sunxi_nand_attach_chip()
1767 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_exec_subop()
1768 u32 cmd = 0, extcmd = 0, cnt = 0, addrs[2] = { }; in sunxi_nfc_exec_subop() local
1773 for (i = 0; i < subop->ninstrs; i++) { in sunxi_nfc_exec_subop()
1774 const struct nand_op_instr *instr = &subop->instrs[i]; in sunxi_nfc_exec_subop()
1776 switch (instr->type) { in sunxi_nfc_exec_subop()
1780 return -EINVAL; in sunxi_nfc_exec_subop()
1783 extcmd |= instr->ctx.cmd.opcode; in sunxi_nfc_exec_subop()
1786 NFC_CMD(instr->ctx.cmd.opcode); in sunxi_nfc_exec_subop()
1794 u32 addr = instr->ctx.addr.addrs[j + start]; in sunxi_nfc_exec_subop()
1808 cnt = min_t(u32, remaining, NFC_SRAM_SIZE); in sunxi_nfc_exec_subop()
1811 if (instr->type == NAND_OP_DATA_OUT_INSTR) { in sunxi_nfc_exec_subop()
1813 memcpy_toio(nfc->regs + NFC_RAM0_BASE, in sunxi_nfc_exec_subop()
1814 instr->ctx.data.buf.out + start, in sunxi_nfc_exec_subop()
1815 cnt); in sunxi_nfc_exec_subop()
1817 inbuf = instr->ctx.data.buf.in + start; in sunxi_nfc_exec_subop()
1833 writel(addrs[0], nfc->regs + NFC_REG_ADDR_LOW); in sunxi_nfc_exec_subop()
1834 writel(addrs[1], nfc->regs + NFC_REG_ADDR_HIGH); in sunxi_nfc_exec_subop()
1839 nfc->regs + in sunxi_nfc_exec_subop()
1844 writel(cnt, nfc->regs + NFC_REG_CNT); in sunxi_nfc_exec_subop()
1846 writel(cmd, nfc->regs + NFC_REG_CMD); in sunxi_nfc_exec_subop()
1849 !(cmd & NFC_WAIT_FLAG) && cnt < 64, in sunxi_nfc_exec_subop()
1855 memcpy_fromio(inbuf, nfc->regs + NFC_RAM0_BASE, cnt); in sunxi_nfc_exec_subop()
1864 subop->instrs[0].ctx.waitrdy.timeout_ms); in sunxi_nfc_soft_waitrdy()
1904 sunxi_nfc_select_chip(nand, op->cs); in sunxi_nfc_exec_op()
1906 if (sunxi_nand->sels[op->cs].rb >= 0) in sunxi_nfc_exec_op()
1926 while (!list_empty(&nfc->chips)) { in sunxi_nand_chips_cleanup()
1927 sunxi_nand = list_first_entry(&nfc->chips, in sunxi_nand_chips_cleanup()
1930 chip = &sunxi_nand->nand; in sunxi_nand_chips_cleanup()
1934 list_del(&sunxi_nand->node); in sunxi_nand_chips_cleanup()
1950 return -EINVAL; in sunxi_nand_chip_init()
1955 return -EINVAL; in sunxi_nand_chip_init()
1961 return -ENOMEM; in sunxi_nand_chip_init()
1963 sunxi_nand->nsels = nsels; in sunxi_nand_chip_init()
1977 return -EINVAL; in sunxi_nand_chip_init()
1980 if (test_and_set_bit(tmp, &nfc->assigned_cs)) { in sunxi_nand_chip_init()
1982 return -EINVAL; in sunxi_nand_chip_init()
1985 sunxi_nand->sels[i].cs = tmp; in sunxi_nand_chip_init()
1989 sunxi_nand->sels[i].rb = tmp; in sunxi_nand_chip_init()
1991 sunxi_nand->sels[i].rb = -1; in sunxi_nand_chip_init()
1994 nand = &sunxi_nand->nand; in sunxi_nand_chip_init()
1996 nand->controller = &nfc->controller; in sunxi_nand_chip_init()
1997 nand->controller->ops = &sunxi_nand_controller_ops; in sunxi_nand_chip_init()
2003 nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in sunxi_nand_chip_init()
2007 mtd->dev.parent = dev; in sunxi_nand_chip_init()
2020 list_add_tail(&sunxi_nand->node, &nfc->chips); in sunxi_nand_chip_init()
2027 struct device_node *np = dev->of_node; in sunxi_nand_chips_init()
2045 if (nfc->caps->has_mdma) in sunxi_nfc_dma_init()
2048 nfc->dmac = dma_request_chan(nfc->dev, "rxtx"); in sunxi_nfc_dma_init()
2049 if (IS_ERR(nfc->dmac)) { in sunxi_nfc_dma_init()
2050 ret = PTR_ERR(nfc->dmac); in sunxi_nfc_dma_init()
2051 if (ret == -EPROBE_DEFER) in sunxi_nfc_dma_init()
2055 dev_warn(nfc->dev, "failed to request rxtx DMA channel: %d\n", ret); in sunxi_nfc_dma_init()
2056 nfc->dmac = NULL; in sunxi_nfc_dma_init()
2060 dmac_cfg.src_addr = r->start + nfc->caps->reg_io_data; in sunxi_nfc_dma_init()
2064 dmac_cfg.src_maxburst = nfc->caps->dma_maxburst; in sunxi_nfc_dma_init()
2065 dmac_cfg.dst_maxburst = nfc->caps->dma_maxburst; in sunxi_nfc_dma_init()
2066 dmaengine_slave_config(nfc->dmac, &dmac_cfg); in sunxi_nfc_dma_init()
2073 struct device *dev = &pdev->dev; in sunxi_nfc_probe()
2081 return -ENOMEM; in sunxi_nfc_probe()
2083 nfc->dev = dev; in sunxi_nfc_probe()
2084 nand_controller_init(&nfc->controller); in sunxi_nfc_probe()
2085 INIT_LIST_HEAD(&nfc->chips); in sunxi_nfc_probe()
2087 nfc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r); in sunxi_nfc_probe()
2088 if (IS_ERR(nfc->regs)) in sunxi_nfc_probe()
2089 return PTR_ERR(nfc->regs); in sunxi_nfc_probe()
2095 nfc->ahb_clk = devm_clk_get_enabled(dev, "ahb"); in sunxi_nfc_probe()
2096 if (IS_ERR(nfc->ahb_clk)) { in sunxi_nfc_probe()
2098 return PTR_ERR(nfc->ahb_clk); in sunxi_nfc_probe()
2101 nfc->mod_clk = devm_clk_get_enabled(dev, "mod"); in sunxi_nfc_probe()
2102 if (IS_ERR(nfc->mod_clk)) { in sunxi_nfc_probe()
2104 return PTR_ERR(nfc->mod_clk); in sunxi_nfc_probe()
2107 nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb"); in sunxi_nfc_probe()
2108 if (IS_ERR(nfc->reset)) in sunxi_nfc_probe()
2109 return PTR_ERR(nfc->reset); in sunxi_nfc_probe()
2111 ret = reset_control_deassert(nfc->reset); in sunxi_nfc_probe()
2117 nfc->caps = of_device_get_match_data(&pdev->dev); in sunxi_nfc_probe()
2118 if (!nfc->caps) { in sunxi_nfc_probe()
2119 ret = -EINVAL; in sunxi_nfc_probe()
2127 writel(0, nfc->regs + NFC_REG_INT); in sunxi_nfc_probe()
2129 0, "sunxi-nand", nfc); in sunxi_nfc_probe()
2149 if (nfc->dmac) in sunxi_nfc_probe()
2150 dma_release_channel(nfc->dmac); in sunxi_nfc_probe()
2152 reset_control_assert(nfc->reset); in sunxi_nfc_probe()
2163 reset_control_assert(nfc->reset); in sunxi_nfc_remove()
2165 if (nfc->dmac) in sunxi_nfc_remove()
2166 dma_release_channel(nfc->dmac); in sunxi_nfc_remove()
2182 .compatible = "allwinner,sun4i-a10-nand",
2186 .compatible = "allwinner,sun8i-a23-nand-controller",