Lines Matching +full:lpc3220 +full:- +full:clk

1 // SPDX-License-Identifier: GPL-2.0-or-later
11 * - Read: Auto Decode
12 * - Write: Auto Encode
13 * - Tested Page Sizes: 2048, 4096
22 #include <linux/clk.h>
32 #include <linux/dma-mapping.h>
134 if (section >= nand_chip->ecc.steps) in lpc32xx_ooblayout_ecc()
135 return -ERANGE; in lpc32xx_ooblayout_ecc()
137 oobregion->offset = ((section + 1) * 16) - nand_chip->ecc.bytes; in lpc32xx_ooblayout_ecc()
138 oobregion->length = nand_chip->ecc.bytes; in lpc32xx_ooblayout_ecc()
148 if (section >= nand_chip->ecc.steps) in lpc32xx_ooblayout_free()
149 return -ERANGE; in lpc32xx_ooblayout_free()
151 oobregion->offset = 16 * section; in lpc32xx_ooblayout_free()
152 oobregion->length = 16 - nand_chip->ecc.bytes; in lpc32xx_ooblayout_free()
178 struct clk *clk; member
203 int mlcsubpages; /* number of 512bytes-subpages */
213 * - readl() of 128 x 32 bits in a loop: ~20us
214 * - DMA read of 512 bytes (32 bit, 4...128 words bursts): ~60us
215 * - DMA read of 512 bytes (32 bit, no bursts): ~100us
221 * FIFO/buffer inside the NAND controller. Most of the time (~400-800us for a
236 writel(MLCCMD_RESET, MLC_CMD(host->io_base)); in lpc32xx_nand_setup()
240 clkrate = clk_get_rate(host->clk); in lpc32xx_nand_setup()
246 writew(MLCLOCKPR_MAGIC, MLC_LOCK_PR(host->io_base)); in lpc32xx_nand_setup()
250 writel(tmp, MLC_ICR(host->io_base)); in lpc32xx_nand_setup()
254 writew(MLCLOCKPR_MAGIC, MLC_LOCK_PR(host->io_base)); in lpc32xx_nand_setup()
258 tmp |= MLCTIMEREG_TCEA_DELAY(clkrate / host->ncfg->tcea_delay + 1); in lpc32xx_nand_setup()
259 tmp |= MLCTIMEREG_BUSY_DELAY(clkrate / host->ncfg->busy_delay + 1); in lpc32xx_nand_setup()
260 tmp |= MLCTIMEREG_NAND_TA(clkrate / host->ncfg->nand_ta + 1); in lpc32xx_nand_setup()
261 tmp |= MLCTIMEREG_RD_HIGH(clkrate / host->ncfg->rd_high + 1); in lpc32xx_nand_setup()
262 tmp |= MLCTIMEREG_RD_LOW(clkrate / host->ncfg->rd_low); in lpc32xx_nand_setup()
263 tmp |= MLCTIMEREG_WR_HIGH(clkrate / host->ncfg->wr_high + 1); in lpc32xx_nand_setup()
264 tmp |= MLCTIMEREG_WR_LOW(clkrate / host->ncfg->wr_low); in lpc32xx_nand_setup()
265 writel(tmp, MLC_TIME_REG(host->io_base)); in lpc32xx_nand_setup()
269 MLC_IRQ_MR(host->io_base)); in lpc32xx_nand_setup()
272 writel(MLCCEH_NORMAL, MLC_CEH(host->io_base)); in lpc32xx_nand_setup()
285 writel(cmd, MLC_CMD(host->io_base)); in lpc32xx_nand_cmd_ctrl()
287 writel(cmd, MLC_ADDR(host->io_base)); in lpc32xx_nand_cmd_ctrl()
298 if ((readb(MLC_ISR(host->io_base)) & in lpc32xx_nand_device_ready()
312 sr = readb(MLC_IRQ_SR(host->io_base)); in lpc3xxx_nand_irq()
314 complete(&host->comp_nand); in lpc3xxx_nand_irq()
316 complete(&host->comp_controller); in lpc3xxx_nand_irq()
326 if (readb(MLC_ISR(host->io_base)) & MLCISR_NAND_READY) in lpc32xx_waitfunc_nand()
329 wait_for_completion(&host->comp_nand); in lpc32xx_waitfunc_nand()
331 while (!(readb(MLC_ISR(host->io_base)) & MLCISR_NAND_READY)) { in lpc32xx_waitfunc_nand()
333 dev_dbg(&mtd->dev, "Warning: NAND not ready.\n"); in lpc32xx_waitfunc_nand()
346 if (readb(MLC_ISR(host->io_base)) & MLCISR_CONTROLLER_READY) in lpc32xx_waitfunc_controller()
349 wait_for_completion(&host->comp_controller); in lpc32xx_waitfunc_controller()
351 while (!(readb(MLC_ISR(host->io_base)) & in lpc32xx_waitfunc_controller()
353 dev_dbg(&mtd->dev, "Warning: Controller not ready.\n"); in lpc32xx_waitfunc_controller()
374 if (host->wp_gpio) in lpc32xx_wp_enable()
375 gpiod_set_value_cansleep(host->wp_gpio, 1); in lpc32xx_wp_enable()
383 if (host->wp_gpio) in lpc32xx_wp_disable()
384 gpiod_set_value_cansleep(host->wp_gpio, 0); in lpc32xx_wp_disable()
401 sg_init_one(&host->sgl, mem, len); in lpc32xx_xmit_dma()
403 res = dma_map_sg(host->dma_chan->device->dev, &host->sgl, 1, in lpc32xx_xmit_dma()
406 dev_err(mtd->dev.parent, "Failed to map sg list\n"); in lpc32xx_xmit_dma()
407 return -ENXIO; in lpc32xx_xmit_dma()
409 desc = dmaengine_prep_slave_sg(host->dma_chan, &host->sgl, 1, dir, in lpc32xx_xmit_dma()
412 dev_err(mtd->dev.parent, "Failed to prepare slave sg\n"); in lpc32xx_xmit_dma()
416 init_completion(&host->comp_dma); in lpc32xx_xmit_dma()
417 desc->callback = lpc32xx_dma_complete_func; in lpc32xx_xmit_dma()
418 desc->callback_param = &host->comp_dma; in lpc32xx_xmit_dma()
421 dma_async_issue_pending(host->dma_chan); in lpc32xx_xmit_dma()
423 wait_for_completion_timeout(&host->comp_dma, msecs_to_jiffies(1000)); in lpc32xx_xmit_dma()
425 dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1, in lpc32xx_xmit_dma()
429 dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1, in lpc32xx_xmit_dma()
431 return -ENXIO; in lpc32xx_xmit_dma()
440 uint8_t *oobbuf = chip->oob_poi; in lpc32xx_read_page()
450 dma_buf = host->dma_buf; in lpc32xx_read_page()
457 /* For all sub-pages */ in lpc32xx_read_page()
458 for (i = 0; i < host->mlcsubpages; i++) { in lpc32xx_read_page()
460 writeb(0x00, MLC_ECC_AUTO_DEC_REG(host->io_base)); in lpc32xx_read_page()
466 mlc_isr = readl(MLC_ISR(host->io_base)); in lpc32xx_read_page()
468 mtd->ecc_stats.failed++; in lpc32xx_read_page()
469 dev_warn(&mtd->dev, "%s: DECODER_FAILURE\n", __func__); in lpc32xx_read_page()
471 mtd->ecc_stats.corrected += ((mlc_isr >> 4) & 0x3) + 1; in lpc32xx_read_page()
483 readl(MLC_BUFF(host->io_base)); in lpc32xx_read_page()
489 readl(MLC_BUFF(host->io_base)); in lpc32xx_read_page()
495 memcpy(buf, dma_buf, mtd->writesize); in lpc32xx_read_page()
506 const uint8_t *oobbuf = chip->oob_poi; in lpc32xx_write_page_lowlevel()
512 dma_buf = host->dma_buf; in lpc32xx_write_page_lowlevel()
513 memcpy(dma_buf, buf, mtd->writesize); in lpc32xx_write_page_lowlevel()
518 for (i = 0; i < host->mlcsubpages; i++) { in lpc32xx_write_page_lowlevel()
520 writeb(0x00, MLC_ECC_ENC_REG(host->io_base)); in lpc32xx_write_page_lowlevel()
531 MLC_BUFF(host->io_base)); in lpc32xx_write_page_lowlevel()
535 writel(*((uint32_t *)(oobbuf)), MLC_BUFF(host->io_base)); in lpc32xx_write_page_lowlevel()
537 writew(*((uint16_t *)(oobbuf)), MLC_BUFF(host->io_base)); in lpc32xx_write_page_lowlevel()
541 writeb(0x00, MLC_ECC_AUTO_ENC_REG(host->io_base)); in lpc32xx_write_page_lowlevel()
554 /* Read whole page - necessary with MLC controller! */ in lpc32xx_read_oob()
555 lpc32xx_read_page(chip, host->dummy_buf, 1, page); in lpc32xx_read_oob()
574 struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); in lpc32xx_dma_setup()
577 host->dma_chan = dma_request_chan(mtd->dev.parent, "rx-tx"); in lpc32xx_dma_setup()
578 if (IS_ERR(host->dma_chan)) { in lpc32xx_dma_setup()
580 if (!host->pdata || !host->pdata->dma_filter) { in lpc32xx_dma_setup()
581 dev_err(mtd->dev.parent, "no DMA platform data\n"); in lpc32xx_dma_setup()
582 return -ENOENT; in lpc32xx_dma_setup()
587 host->dma_chan = dma_request_channel(mask, host->pdata->dma_filter, "nand-mlc"); in lpc32xx_dma_setup()
589 if (!host->dma_chan) { in lpc32xx_dma_setup()
590 dev_err(mtd->dev.parent, "Failed to request DMA channel\n"); in lpc32xx_dma_setup()
591 return -EBUSY; in lpc32xx_dma_setup()
597 * should ignore it. With the default (DMA_MEM_TO_MEM), the amba-pl08x in lpc32xx_dma_setup()
600 host->dma_slave_config.direction = DMA_DEV_TO_MEM; in lpc32xx_dma_setup()
601 host->dma_slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in lpc32xx_dma_setup()
602 host->dma_slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in lpc32xx_dma_setup()
603 host->dma_slave_config.src_maxburst = 128; in lpc32xx_dma_setup()
604 host->dma_slave_config.dst_maxburst = 128; in lpc32xx_dma_setup()
606 host->dma_slave_config.device_fc = false; in lpc32xx_dma_setup()
607 host->dma_slave_config.src_addr = MLC_BUFF(host->io_base_phy); in lpc32xx_dma_setup()
608 host->dma_slave_config.dst_addr = MLC_BUFF(host->io_base_phy); in lpc32xx_dma_setup()
609 if (dmaengine_slave_config(host->dma_chan, &host->dma_slave_config)) { in lpc32xx_dma_setup()
610 dev_err(mtd->dev.parent, "Failed to setup DMA slave\n"); in lpc32xx_dma_setup()
616 dma_release_channel(host->dma_chan); in lpc32xx_dma_setup()
617 return -ENXIO; in lpc32xx_dma_setup()
623 struct device_node *np = dev->of_node; in lpc32xx_parse_dt()
629 of_property_read_u32(np, "nxp,tcea-delay", &ncfg->tcea_delay); in lpc32xx_parse_dt()
630 of_property_read_u32(np, "nxp,busy-delay", &ncfg->busy_delay); in lpc32xx_parse_dt()
631 of_property_read_u32(np, "nxp,nand-ta", &ncfg->nand_ta); in lpc32xx_parse_dt()
632 of_property_read_u32(np, "nxp,rd-high", &ncfg->rd_high); in lpc32xx_parse_dt()
633 of_property_read_u32(np, "nxp,rd-low", &ncfg->rd_low); in lpc32xx_parse_dt()
634 of_property_read_u32(np, "nxp,wr-high", &ncfg->wr_high); in lpc32xx_parse_dt()
635 of_property_read_u32(np, "nxp,wr-low", &ncfg->wr_low); in lpc32xx_parse_dt()
637 if (!ncfg->tcea_delay || !ncfg->busy_delay || !ncfg->nand_ta || in lpc32xx_parse_dt()
638 !ncfg->rd_high || !ncfg->rd_low || !ncfg->wr_high || in lpc32xx_parse_dt()
639 !ncfg->wr_low) { in lpc32xx_parse_dt()
651 struct device *dev = &host->pdev->dev; in lpc32xx_nand_attach_chip()
653 if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) in lpc32xx_nand_attach_chip()
656 host->dma_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL); in lpc32xx_nand_attach_chip()
657 if (!host->dma_buf) in lpc32xx_nand_attach_chip()
658 return -ENOMEM; in lpc32xx_nand_attach_chip()
660 host->dummy_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL); in lpc32xx_nand_attach_chip()
661 if (!host->dummy_buf) in lpc32xx_nand_attach_chip()
662 return -ENOMEM; in lpc32xx_nand_attach_chip()
664 chip->ecc.size = 512; in lpc32xx_nand_attach_chip()
665 chip->ecc.hwctl = lpc32xx_ecc_enable; in lpc32xx_nand_attach_chip()
666 chip->ecc.read_page_raw = lpc32xx_read_page; in lpc32xx_nand_attach_chip()
667 chip->ecc.read_page = lpc32xx_read_page; in lpc32xx_nand_attach_chip()
668 chip->ecc.write_page_raw = lpc32xx_write_page_lowlevel; in lpc32xx_nand_attach_chip()
669 chip->ecc.write_page = lpc32xx_write_page_lowlevel; in lpc32xx_nand_attach_chip()
670 chip->ecc.write_oob = lpc32xx_write_oob; in lpc32xx_nand_attach_chip()
671 chip->ecc.read_oob = lpc32xx_read_oob; in lpc32xx_nand_attach_chip()
672 chip->ecc.strength = 4; in lpc32xx_nand_attach_chip()
673 chip->ecc.bytes = 10; in lpc32xx_nand_attach_chip()
676 host->mlcsubpages = mtd->writesize / 512; in lpc32xx_nand_attach_chip()
697 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); in lpc32xx_nand_probe()
699 return -ENOMEM; in lpc32xx_nand_probe()
701 host->pdev = pdev; in lpc32xx_nand_probe()
703 host->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &rc); in lpc32xx_nand_probe()
704 if (IS_ERR(host->io_base)) in lpc32xx_nand_probe()
705 return PTR_ERR(host->io_base); in lpc32xx_nand_probe()
707 host->io_base_phy = rc->start; in lpc32xx_nand_probe()
709 nand_chip = &host->nand_chip; in lpc32xx_nand_probe()
711 if (pdev->dev.of_node) in lpc32xx_nand_probe()
712 host->ncfg = lpc32xx_parse_dt(&pdev->dev); in lpc32xx_nand_probe()
713 if (!host->ncfg) { in lpc32xx_nand_probe()
714 dev_err(&pdev->dev, in lpc32xx_nand_probe()
716 return -ENOENT; in lpc32xx_nand_probe()
720 host->wp_gpio = gpiod_get_optional(&pdev->dev, NULL, GPIOD_OUT_LOW); in lpc32xx_nand_probe()
721 res = PTR_ERR_OR_ZERO(host->wp_gpio); in lpc32xx_nand_probe()
723 if (res != -EPROBE_DEFER) in lpc32xx_nand_probe()
724 dev_err(&pdev->dev, "WP GPIO is not available: %d\n", in lpc32xx_nand_probe()
729 gpiod_set_consumer_name(host->wp_gpio, "NAND WP"); in lpc32xx_nand_probe()
731 host->pdata = dev_get_platdata(&pdev->dev); in lpc32xx_nand_probe()
735 nand_set_flash_node(nand_chip, pdev->dev.of_node); in lpc32xx_nand_probe()
736 mtd->dev.parent = &pdev->dev; in lpc32xx_nand_probe()
739 host->clk = clk_get(&pdev->dev, NULL); in lpc32xx_nand_probe()
740 if (IS_ERR(host->clk)) { in lpc32xx_nand_probe()
741 dev_err(&pdev->dev, "Clock initialization failure\n"); in lpc32xx_nand_probe()
742 res = -ENOENT; in lpc32xx_nand_probe()
745 res = clk_prepare_enable(host->clk); in lpc32xx_nand_probe()
749 nand_chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl; in lpc32xx_nand_probe()
750 nand_chip->legacy.dev_ready = lpc32xx_nand_device_ready; in lpc32xx_nand_probe()
751 nand_chip->legacy.chip_delay = 25; /* us */ in lpc32xx_nand_probe()
752 nand_chip->legacy.IO_ADDR_R = MLC_DATA(host->io_base); in lpc32xx_nand_probe()
753 nand_chip->legacy.IO_ADDR_W = MLC_DATA(host->io_base); in lpc32xx_nand_probe()
761 nand_chip->legacy.waitfunc = lpc32xx_waitfunc; in lpc32xx_nand_probe()
763 nand_chip->options = NAND_NO_SUBPAGE_WRITE; in lpc32xx_nand_probe()
764 nand_chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; in lpc32xx_nand_probe()
765 nand_chip->bbt_td = &lpc32xx_nand_bbt; in lpc32xx_nand_probe()
766 nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror; in lpc32xx_nand_probe()
771 res = -EIO; in lpc32xx_nand_probe()
777 readb(MLC_IRQ_SR(host->io_base)); in lpc32xx_nand_probe()
779 init_completion(&host->comp_nand); in lpc32xx_nand_probe()
780 init_completion(&host->comp_controller); in lpc32xx_nand_probe()
782 host->irq = platform_get_irq(pdev, 0); in lpc32xx_nand_probe()
783 if (host->irq < 0) { in lpc32xx_nand_probe()
784 res = -EINVAL; in lpc32xx_nand_probe()
788 if (request_irq(host->irq, &lpc3xxx_nand_irq, in lpc32xx_nand_probe()
790 dev_err(&pdev->dev, "Error requesting NAND IRQ\n"); in lpc32xx_nand_probe()
791 res = -ENXIO; in lpc32xx_nand_probe()
799 nand_chip->legacy.dummy_controller.ops = &lpc32xx_nand_controller_ops; in lpc32xx_nand_probe()
804 mtd->name = DRV_NAME; in lpc32xx_nand_probe()
806 res = mtd_device_register(mtd, host->ncfg->parts, in lpc32xx_nand_probe()
807 host->ncfg->num_parts); in lpc32xx_nand_probe()
816 free_irq(host->irq, host); in lpc32xx_nand_probe()
819 dma_release_channel(host->dma_chan); in lpc32xx_nand_probe()
821 clk_disable_unprepare(host->clk); in lpc32xx_nand_probe()
823 clk_put(host->clk); in lpc32xx_nand_probe()
826 gpiod_put(host->wp_gpio); in lpc32xx_nand_probe()
837 struct nand_chip *chip = &host->nand_chip; in lpc32xx_nand_remove()
844 free_irq(host->irq, host); in lpc32xx_nand_remove()
846 dma_release_channel(host->dma_chan); in lpc32xx_nand_remove()
848 clk_disable_unprepare(host->clk); in lpc32xx_nand_remove()
849 clk_put(host->clk); in lpc32xx_nand_remove()
852 gpiod_put(host->wp_gpio); in lpc32xx_nand_remove()
860 /* Re-enable NAND clock */ in lpc32xx_nand_resume()
861 ret = clk_prepare_enable(host->clk); in lpc32xx_nand_resume()
882 clk_disable_unprepare(host->clk); in lpc32xx_nand_suspend()
887 { .compatible = "nxp,lpc3220-mlc" },