Lines Matching full:nfc
6 * https://github.com/yuq/sunxi-nfc-mtd
165 * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the NFC
263 struct sunxi_nfc *nfc = dev_id; in sunxi_nfc_interrupt() local
264 u32 st = readl(nfc->regs + NFC_REG_ST); in sunxi_nfc_interrupt()
265 u32 ien = readl(nfc->regs + NFC_REG_INT); in sunxi_nfc_interrupt()
271 complete(&nfc->complete); in sunxi_nfc_interrupt()
273 writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST); in sunxi_nfc_interrupt()
274 writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT); in sunxi_nfc_interrupt()
279 static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, in sunxi_nfc_wait_events() argument
291 init_completion(&nfc->complete); in sunxi_nfc_wait_events()
293 writel(events, nfc->regs + NFC_REG_INT); in sunxi_nfc_wait_events()
295 ret = wait_for_completion_timeout(&nfc->complete, in sunxi_nfc_wait_events()
302 writel(0, nfc->regs + NFC_REG_INT); in sunxi_nfc_wait_events()
306 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status, in sunxi_nfc_wait_events()
311 writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST); in sunxi_nfc_wait_events()
314 dev_err(nfc->dev, "wait interrupt timedout\n"); in sunxi_nfc_wait_events()
319 static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc) in sunxi_nfc_wait_cmd_fifo_empty() argument
324 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status, in sunxi_nfc_wait_cmd_fifo_empty()
328 dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n"); in sunxi_nfc_wait_cmd_fifo_empty()
333 static int sunxi_nfc_rst(struct sunxi_nfc *nfc) in sunxi_nfc_rst() argument
338 writel(0, nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_rst()
339 writel(NFC_RESET, nfc->regs + NFC_REG_CTL); in sunxi_nfc_rst()
341 ret = readl_poll_timeout(nfc->regs + NFC_REG_CTL, ctl, in sunxi_nfc_rst()
345 dev_err(nfc->dev, "wait for NAND controller reset timedout\n"); in sunxi_nfc_rst()
350 static int sunxi_nfc_dma_op_prepare(struct sunxi_nfc *nfc, const void *buf, in sunxi_nfc_dma_op_prepare() argument
366 ret = dma_map_sg(nfc->dev, sg, 1, ddir); in sunxi_nfc_dma_op_prepare()
370 if (!nfc->caps->has_mdma) { in sunxi_nfc_dma_op_prepare()
371 dmad = dmaengine_prep_slave_sg(nfc->dmac, sg, 1, tdir, DMA_CTRL_ACK); in sunxi_nfc_dma_op_prepare()
378 writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD, in sunxi_nfc_dma_op_prepare()
379 nfc->regs + NFC_REG_CTL); in sunxi_nfc_dma_op_prepare()
380 writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM); in sunxi_nfc_dma_op_prepare()
381 writel(chunksize, nfc->regs + NFC_REG_CNT); in sunxi_nfc_dma_op_prepare()
383 if (nfc->caps->has_mdma) { in sunxi_nfc_dma_op_prepare()
384 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_DMA_TYPE_NORMAL, in sunxi_nfc_dma_op_prepare()
385 nfc->regs + NFC_REG_CTL); in sunxi_nfc_dma_op_prepare()
386 writel(chunksize * nchunks, nfc->regs + NFC_REG_MDMA_CNT); in sunxi_nfc_dma_op_prepare()
387 writel(sg_dma_address(sg), nfc->regs + NFC_REG_MDMA_ADDR); in sunxi_nfc_dma_op_prepare()
399 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD, in sunxi_nfc_dma_op_prepare()
400 nfc->regs + NFC_REG_CTL); in sunxi_nfc_dma_op_prepare()
403 dma_unmap_sg(nfc->dev, sg, 1, ddir); in sunxi_nfc_dma_op_prepare()
407 static void sunxi_nfc_dma_op_cleanup(struct sunxi_nfc *nfc, in sunxi_nfc_dma_op_cleanup() argument
411 dma_unmap_sg(nfc->dev, sg, 1, ddir); in sunxi_nfc_dma_op_cleanup()
412 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD, in sunxi_nfc_dma_op_cleanup()
413 nfc->regs + NFC_REG_CTL); in sunxi_nfc_dma_op_cleanup()
420 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); in sunxi_nfc_select_chip() local
427 ctl = readl(nfc->regs + NFC_REG_CTL) & in sunxi_nfc_select_chip()
435 writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA); in sunxi_nfc_select_chip()
437 if (nfc->clk_rate != sunxi_nand->clk_rate) { in sunxi_nfc_select_chip()
438 clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate); in sunxi_nfc_select_chip()
439 nfc->clk_rate = sunxi_nand->clk_rate; in sunxi_nfc_select_chip()
442 writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL); in sunxi_nfc_select_chip()
443 writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG); in sunxi_nfc_select_chip()
444 writel(ctl, nfc->regs + NFC_REG_CTL); in sunxi_nfc_select_chip()
450 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); in sunxi_nfc_read_buf() local
461 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); in sunxi_nfc_read_buf()
465 writel(cnt, nfc->regs + NFC_REG_CNT); in sunxi_nfc_read_buf()
467 writel(tmp, nfc->regs + NFC_REG_CMD); in sunxi_nfc_read_buf()
473 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); in sunxi_nfc_read_buf()
478 memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE, in sunxi_nfc_read_buf()
488 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); in sunxi_nfc_write_buf() local
499 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); in sunxi_nfc_write_buf()
503 writel(cnt, nfc->regs + NFC_REG_CNT); in sunxi_nfc_write_buf()
504 memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt); in sunxi_nfc_write_buf()
507 writel(tmp, nfc->regs + NFC_REG_CMD); in sunxi_nfc_write_buf()
513 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); in sunxi_nfc_write_buf()
626 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_randomizer_config() local
627 u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_config()
633 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_config()
635 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK; in sunxi_nfc_randomizer_config()
636 writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_config()
641 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_randomizer_enable() local
646 writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN, in sunxi_nfc_randomizer_enable()
647 nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_enable()
652 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_randomizer_disable() local
657 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN, in sunxi_nfc_randomizer_disable()
658 nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_randomizer_disable()
691 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_enable() local
694 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_hw_ecc_enable()
703 writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_hw_ecc_enable()
708 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_disable() local
710 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN, in sunxi_nfc_hw_ecc_disable()
711 nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_hw_ecc_disable()
730 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_get_prot_oob_bytes() local
732 sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)), in sunxi_nfc_hw_ecc_get_prot_oob_bytes()
744 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_set_prot_oob_bytes() local
755 nfc->regs + NFC_REG_USER_DATA(step)); in sunxi_nfc_hw_ecc_set_prot_oob_bytes()
774 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_correct() local
786 if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) { in sunxi_nfc_hw_ecc_correct()
802 tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step)); in sunxi_nfc_hw_ecc_correct()
814 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_read_chunk() local
828 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); in sunxi_nfc_hw_ecc_read_chunk()
834 nfc->regs + NFC_REG_CMD); in sunxi_nfc_hw_ecc_read_chunk()
836 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0); in sunxi_nfc_hw_ecc_read_chunk()
844 readl(nfc->regs + NFC_REG_ECC_ST), in sunxi_nfc_hw_ecc_read_chunk()
858 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, in sunxi_nfc_hw_ecc_read_chunk()
870 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); in sunxi_nfc_hw_ecc_read_chunk()
919 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_read_chunks_dma() local
927 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); in sunxi_nfc_hw_ecc_read_chunks_dma()
931 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks, in sunxi_nfc_hw_ecc_read_chunks_dma()
941 NAND_CMD_READSTART, nfc->regs + NFC_REG_RCMD_SET); in sunxi_nfc_hw_ecc_read_chunks_dma()
945 if (nfc->caps->has_mdma) in sunxi_nfc_hw_ecc_read_chunks_dma()
948 dma_async_issue_pending(nfc->dmac); in sunxi_nfc_hw_ecc_read_chunks_dma()
951 nfc->regs + NFC_REG_CMD); in sunxi_nfc_hw_ecc_read_chunks_dma()
953 ret = sunxi_nfc_wait_events(nfc, wait, false, 0); in sunxi_nfc_hw_ecc_read_chunks_dma()
954 if (ret && !nfc->caps->has_mdma) in sunxi_nfc_hw_ecc_read_chunks_dma()
955 dmaengine_terminate_all(nfc->dmac); in sunxi_nfc_hw_ecc_read_chunks_dma()
960 sunxi_nfc_dma_op_cleanup(nfc, DMA_FROM_DEVICE, &sg); in sunxi_nfc_hw_ecc_read_chunks_dma()
965 status = readl(nfc->regs + NFC_REG_ECC_ST); in sunxi_nfc_hw_ecc_read_chunks_dma()
1048 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_write_chunk() local
1060 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); in sunxi_nfc_hw_ecc_write_chunk()
1069 nfc->regs + NFC_REG_CMD); in sunxi_nfc_hw_ecc_write_chunk()
1071 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0); in sunxi_nfc_hw_ecc_write_chunk()
1292 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_hw_ecc_write_page_dma() local
1300 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); in sunxi_nfc_hw_ecc_write_page_dma()
1304 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps, in sunxi_nfc_hw_ecc_write_page_dma()
1322 nfc->regs + NFC_REG_WCMD_SET); in sunxi_nfc_hw_ecc_write_page_dma()
1326 if (nfc->caps->has_mdma) in sunxi_nfc_hw_ecc_write_page_dma()
1329 dma_async_issue_pending(nfc->dmac); in sunxi_nfc_hw_ecc_write_page_dma()
1333 nfc->regs + NFC_REG_CMD); in sunxi_nfc_hw_ecc_write_page_dma()
1335 ret = sunxi_nfc_wait_events(nfc, wait, false, 0); in sunxi_nfc_hw_ecc_write_page_dma()
1336 if (ret && !nfc->caps->has_mdma) in sunxi_nfc_hw_ecc_write_page_dma()
1337 dmaengine_terminate_all(nfc->dmac); in sunxi_nfc_hw_ecc_write_page_dma()
1342 sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); in sunxi_nfc_hw_ecc_write_page_dma()
1405 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); in sunxi_nfc_setup_interface() local
1505 dev_err(nfc->dev, "unsupported tWB\n"); in sunxi_nfc_setup_interface()
1511 dev_err(nfc->dev, "unsupported tADL\n"); in sunxi_nfc_setup_interface()
1517 dev_err(nfc->dev, "unsupported tWHR\n"); in sunxi_nfc_setup_interface()
1524 dev_err(nfc->dev, "unsupported tRHW\n"); in sunxi_nfc_setup_interface()
1550 real_clk_rate = clk_round_rate(nfc->mod_clk, sunxi_nand->clk_rate); in sunxi_nfc_setup_interface()
1552 dev_err(nfc->dev, "Unable to round clk %lu\n", in sunxi_nfc_setup_interface()
1633 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nand_hw_ecc_ctrl_init() local
1695 dev_err(nfc->dev, "unsupported strength\n"); in sunxi_nand_hw_ecc_ctrl_init()
1719 if (nfc->dmac || nfc->caps->has_mdma) { in sunxi_nand_hw_ecc_ctrl_init()
1800 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); in sunxi_nfc_exec_subop() local
1846 memcpy_toio(nfc->regs + NFC_RAM0_BASE, in sunxi_nfc_exec_subop()
1861 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); in sunxi_nfc_exec_subop()
1866 writel(addrs[0], nfc->regs + NFC_REG_ADDR_LOW); in sunxi_nfc_exec_subop()
1867 writel(addrs[1], nfc->regs + NFC_REG_ADDR_HIGH); in sunxi_nfc_exec_subop()
1872 nfc->regs + in sunxi_nfc_exec_subop()
1877 writel(cnt, nfc->regs + NFC_REG_CNT); in sunxi_nfc_exec_subop()
1879 writel(cmd, nfc->regs + NFC_REG_CMD); in sunxi_nfc_exec_subop()
1881 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, in sunxi_nfc_exec_subop()
1888 memcpy_fromio(inbuf, nfc->regs + NFC_RAM0_BASE, cnt); in sunxi_nfc_exec_subop()
1953 static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, in sunxi_nand_chip_init() argument
1995 if (test_and_set_bit(tmp, &nfc->assigned_cs)) { in sunxi_nand_chip_init()
2011 nand->controller = &nfc->controller; in sunxi_nand_chip_init()
2035 list_add_tail(&sunxi_nand->node, &nfc->chips); in sunxi_nand_chip_init()
2040 static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc) in sunxi_nand_chips_init() argument
2053 ret = sunxi_nand_chip_init(dev, nfc, nand_np); in sunxi_nand_chips_init()
2063 static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc) in sunxi_nand_chips_cleanup() argument
2069 while (!list_empty(&nfc->chips)) { in sunxi_nand_chips_cleanup()
2070 sunxi_nand = list_first_entry(&nfc->chips, in sunxi_nand_chips_cleanup()
2082 static int sunxi_nfc_dma_init(struct sunxi_nfc *nfc, struct resource *r) in sunxi_nfc_dma_init() argument
2086 if (nfc->caps->has_mdma) in sunxi_nfc_dma_init()
2089 nfc->dmac = dma_request_chan(nfc->dev, "rxtx"); in sunxi_nfc_dma_init()
2090 if (IS_ERR(nfc->dmac)) { in sunxi_nfc_dma_init()
2091 ret = PTR_ERR(nfc->dmac); in sunxi_nfc_dma_init()
2096 dev_warn(nfc->dev, "failed to request rxtx DMA channel: %d\n", ret); in sunxi_nfc_dma_init()
2097 nfc->dmac = NULL; in sunxi_nfc_dma_init()
2101 dmac_cfg.src_addr = r->start + nfc->caps->reg_io_data; in sunxi_nfc_dma_init()
2105 dmac_cfg.src_maxburst = nfc->caps->dma_maxburst; in sunxi_nfc_dma_init()
2106 dmac_cfg.dst_maxburst = nfc->caps->dma_maxburst; in sunxi_nfc_dma_init()
2107 dmaengine_slave_config(nfc->dmac, &dmac_cfg); in sunxi_nfc_dma_init()
2116 struct sunxi_nfc *nfc; in sunxi_nfc_probe() local
2120 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); in sunxi_nfc_probe()
2121 if (!nfc) in sunxi_nfc_probe()
2124 nfc->dev = dev; in sunxi_nfc_probe()
2125 nand_controller_init(&nfc->controller); in sunxi_nfc_probe()
2126 INIT_LIST_HEAD(&nfc->chips); in sunxi_nfc_probe()
2129 nfc->regs = devm_ioremap_resource(dev, r); in sunxi_nfc_probe()
2130 if (IS_ERR(nfc->regs)) in sunxi_nfc_probe()
2131 return PTR_ERR(nfc->regs); in sunxi_nfc_probe()
2137 nfc->ahb_clk = devm_clk_get(dev, "ahb"); in sunxi_nfc_probe()
2138 if (IS_ERR(nfc->ahb_clk)) { in sunxi_nfc_probe()
2140 return PTR_ERR(nfc->ahb_clk); in sunxi_nfc_probe()
2143 ret = clk_prepare_enable(nfc->ahb_clk); in sunxi_nfc_probe()
2147 nfc->mod_clk = devm_clk_get(dev, "mod"); in sunxi_nfc_probe()
2148 if (IS_ERR(nfc->mod_clk)) { in sunxi_nfc_probe()
2150 ret = PTR_ERR(nfc->mod_clk); in sunxi_nfc_probe()
2154 ret = clk_prepare_enable(nfc->mod_clk); in sunxi_nfc_probe()
2158 nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb"); in sunxi_nfc_probe()
2159 if (IS_ERR(nfc->reset)) { in sunxi_nfc_probe()
2160 ret = PTR_ERR(nfc->reset); in sunxi_nfc_probe()
2164 ret = reset_control_deassert(nfc->reset); in sunxi_nfc_probe()
2170 nfc->caps = of_device_get_match_data(&pdev->dev); in sunxi_nfc_probe()
2171 if (!nfc->caps) { in sunxi_nfc_probe()
2176 ret = sunxi_nfc_rst(nfc); in sunxi_nfc_probe()
2180 writel(0, nfc->regs + NFC_REG_INT); in sunxi_nfc_probe()
2182 0, "sunxi-nand", nfc); in sunxi_nfc_probe()
2186 ret = sunxi_nfc_dma_init(nfc, r); in sunxi_nfc_probe()
2191 platform_set_drvdata(pdev, nfc); in sunxi_nfc_probe()
2193 ret = sunxi_nand_chips_init(dev, nfc); in sunxi_nfc_probe()
2202 if (nfc->dmac) in sunxi_nfc_probe()
2203 dma_release_channel(nfc->dmac); in sunxi_nfc_probe()
2205 reset_control_assert(nfc->reset); in sunxi_nfc_probe()
2207 clk_disable_unprepare(nfc->mod_clk); in sunxi_nfc_probe()
2209 clk_disable_unprepare(nfc->ahb_clk); in sunxi_nfc_probe()
2216 struct sunxi_nfc *nfc = platform_get_drvdata(pdev); in sunxi_nfc_remove() local
2218 sunxi_nand_chips_cleanup(nfc); in sunxi_nfc_remove()
2220 reset_control_assert(nfc->reset); in sunxi_nfc_remove()
2222 if (nfc->dmac) in sunxi_nfc_remove()
2223 dma_release_channel(nfc->dmac); in sunxi_nfc_remove()
2224 clk_disable_unprepare(nfc->mod_clk); in sunxi_nfc_remove()
2225 clk_disable_unprepare(nfc->ahb_clk); in sunxi_nfc_remove()