Lines Matching +full:ls1021a +full:- +full:qspi

1 // SPDX-License-Identifier: GPL-2.0+
18 * Based on the original fsl-quadspi.c SPI NOR driver:
42 #include <linux/spi/spi-mem.h>
158 #define LUT_PAD(x) (fls(x) - 1)
164 * ---------------------------------------------------
166 * ---------------------------------------------------
279 return q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN; in needs_swap_endian()
284 return q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK; in needs_4x_clock()
289 return q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890; in needs_fill_txfifo()
294 return q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618; in needs_wakeup_wait_mode()
299 return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL); in needs_amba_base_offset()
304 return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING; in needs_tdh_setting()
308 * An IC bug makes it necessary to rearrange the 32-bit data.
317 * R/W functions for big- or little-endian registers:
318 * The QSPI controller's endianness is independent of
320 * core is little-endian the QSPI controller can use
321 * big-endian or little-endian.
325 if (q->devtype_data->little_endian) in qspi_writel()
333 if (q->devtype_data->little_endian) in qspi_readl()
345 reg = qspi_readl(q, q->iobase + QUADSPI_FR); in fsl_qspi_irq_handler()
346 qspi_writel(q, reg, q->iobase + QUADSPI_FR); in fsl_qspi_irq_handler()
349 complete(&q->c); in fsl_qspi_irq_handler()
351 dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", 0, reg); in fsl_qspi_irq_handler()
364 return -ENOTSUPP; in fsl_qspi_check_buswidth()
370 struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); in fsl_qspi_supports_op()
373 ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth); in fsl_qspi_supports_op()
375 if (op->addr.nbytes) in fsl_qspi_supports_op()
376 ret |= fsl_qspi_check_buswidth(q, op->addr.buswidth); in fsl_qspi_supports_op()
378 if (op->dummy.nbytes) in fsl_qspi_supports_op()
379 ret |= fsl_qspi_check_buswidth(q, op->dummy.buswidth); in fsl_qspi_supports_op()
381 if (op->data.nbytes) in fsl_qspi_supports_op()
382 ret |= fsl_qspi_check_buswidth(q, op->data.buswidth); in fsl_qspi_supports_op()
391 if (op->addr.nbytes + in fsl_qspi_supports_op()
392 (op->dummy.nbytes ? 1:0) + in fsl_qspi_supports_op()
393 (op->data.nbytes ? 1:0) > 6) in fsl_qspi_supports_op()
397 if (op->dummy.nbytes && in fsl_qspi_supports_op()
398 (op->dummy.nbytes * 8 / op->dummy.buswidth > 64)) in fsl_qspi_supports_op()
402 if (op->data.dir == SPI_MEM_DATA_IN && in fsl_qspi_supports_op()
403 (op->data.nbytes > q->devtype_data->ahb_buf_size || in fsl_qspi_supports_op()
404 (op->data.nbytes > q->devtype_data->rxfifo - 4 && in fsl_qspi_supports_op()
405 !IS_ALIGNED(op->data.nbytes, 8)))) in fsl_qspi_supports_op()
408 if (op->data.dir == SPI_MEM_DATA_OUT && in fsl_qspi_supports_op()
409 op->data.nbytes > q->devtype_data->txfifo) in fsl_qspi_supports_op()
418 void __iomem *base = q->iobase; in fsl_qspi_prepare_lut()
422 lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), in fsl_qspi_prepare_lut()
423 op->cmd.opcode); in fsl_qspi_prepare_lut()
430 for (i = 0; i < op->addr.nbytes; i++) { in fsl_qspi_prepare_lut()
431 u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); in fsl_qspi_prepare_lut()
434 LUT_PAD(op->addr.buswidth), in fsl_qspi_prepare_lut()
439 if (op->dummy.nbytes) { in fsl_qspi_prepare_lut()
441 LUT_PAD(op->dummy.buswidth), in fsl_qspi_prepare_lut()
442 op->dummy.nbytes * 8 / in fsl_qspi_prepare_lut()
443 op->dummy.buswidth); in fsl_qspi_prepare_lut()
447 if (op->data.nbytes) { in fsl_qspi_prepare_lut()
449 op->data.dir == SPI_MEM_DATA_IN ? in fsl_qspi_prepare_lut()
451 LUT_PAD(op->data.buswidth), in fsl_qspi_prepare_lut()
459 qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); in fsl_qspi_prepare_lut()
460 qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); in fsl_qspi_prepare_lut()
467 qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); in fsl_qspi_prepare_lut()
468 qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); in fsl_qspi_prepare_lut()
475 ret = clk_prepare_enable(q->clk_en); in fsl_qspi_clk_prep_enable()
479 ret = clk_prepare_enable(q->clk); in fsl_qspi_clk_prep_enable()
481 clk_disable_unprepare(q->clk_en); in fsl_qspi_clk_prep_enable()
486 cpu_latency_qos_add_request(&q->pm_qos_req, 0); in fsl_qspi_clk_prep_enable()
494 cpu_latency_qos_remove_request(&q->pm_qos_req); in fsl_qspi_clk_disable_unprep()
496 clk_disable_unprepare(q->clk); in fsl_qspi_clk_disable_unprep()
497 clk_disable_unprepare(q->clk_en); in fsl_qspi_clk_disable_unprep()
511 reg = qspi_readl(q, q->iobase + QUADSPI_MCR); in fsl_qspi_invalidate()
513 qspi_writel(q, reg, q->iobase + QUADSPI_MCR); in fsl_qspi_invalidate()
522 qspi_writel(q, reg, q->iobase + QUADSPI_MCR); in fsl_qspi_invalidate()
528 unsigned long rate = op->max_freq; in fsl_qspi_select_mem()
531 if (q->selected == spi_get_chipselect(spi, 0)) in fsl_qspi_select_mem()
539 ret = clk_set_rate(q->clk, rate); in fsl_qspi_select_mem()
547 q->selected = spi_get_chipselect(spi, 0); in fsl_qspi_select_mem()
554 memcpy_fromio(op->data.buf.in, in fsl_qspi_read_ahb()
555 q->ahb_addr + q->selected * q->devtype_data->ahb_buf_size, in fsl_qspi_read_ahb()
556 op->data.nbytes); in fsl_qspi_read_ahb()
562 void __iomem *base = q->iobase; in fsl_qspi_fill_txfifo()
566 for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) { in fsl_qspi_fill_txfifo()
567 memcpy(&val, op->data.buf.out + i, 4); in fsl_qspi_fill_txfifo()
572 if (i < op->data.nbytes) { in fsl_qspi_fill_txfifo()
573 memcpy(&val, op->data.buf.out + i, op->data.nbytes - i); in fsl_qspi_fill_txfifo()
579 for (i = op->data.nbytes; i < 16; i += 4) in fsl_qspi_fill_txfifo()
587 void __iomem *base = q->iobase; in fsl_qspi_read_rxfifo()
589 u8 *buf = op->data.buf.in; in fsl_qspi_read_rxfifo()
592 for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) { in fsl_qspi_read_rxfifo()
598 if (i < op->data.nbytes) { in fsl_qspi_read_rxfifo()
601 memcpy(buf + i, &val, op->data.nbytes - i); in fsl_qspi_read_rxfifo()
607 void __iomem *base = q->iobase; in fsl_qspi_do_op()
610 init_completion(&q->c); in fsl_qspi_do_op()
617 qspi_writel(q, op->data.nbytes | QUADSPI_IPCR_SEQID(SEQID_LUT), in fsl_qspi_do_op()
621 if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) in fsl_qspi_do_op()
622 err = -ETIMEDOUT; in fsl_qspi_do_op()
624 if (!err && op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN) in fsl_qspi_do_op()
635 if (!q->devtype_data->little_endian) in fsl_qspi_readl_poll_tout()
644 struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); in fsl_qspi_exec_op()
645 void __iomem *base = q->iobase; in fsl_qspi_exec_op()
648 int invalid_mstrid = q->devtype_data->invalid_mstrid; in fsl_qspi_exec_op()
650 mutex_lock(&q->lock); in fsl_qspi_exec_op()
656 fsl_qspi_select_mem(q, mem->spi, op); in fsl_qspi_exec_op()
659 addr_offset = q->memmap_phy; in fsl_qspi_exec_op()
662 q->selected * q->devtype_data->ahb_buf_size + addr_offset, in fsl_qspi_exec_op()
683 if (op->data.nbytes > (q->devtype_data->rxfifo - 4) && in fsl_qspi_exec_op()
684 op->data.dir == SPI_MEM_DATA_IN) { in fsl_qspi_exec_op()
690 if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) in fsl_qspi_exec_op()
699 mutex_unlock(&q->lock); in fsl_qspi_exec_op()
706 struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); in fsl_qspi_adjust_op_size()
708 if (op->data.dir == SPI_MEM_DATA_OUT) { in fsl_qspi_adjust_op_size()
709 if (op->data.nbytes > q->devtype_data->txfifo) in fsl_qspi_adjust_op_size()
710 op->data.nbytes = q->devtype_data->txfifo; in fsl_qspi_adjust_op_size()
712 if (op->data.nbytes > q->devtype_data->ahb_buf_size) in fsl_qspi_adjust_op_size()
713 op->data.nbytes = q->devtype_data->ahb_buf_size; in fsl_qspi_adjust_op_size()
714 else if (op->data.nbytes > (q->devtype_data->rxfifo - 4)) in fsl_qspi_adjust_op_size()
715 op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8); in fsl_qspi_adjust_op_size()
723 void __iomem *base = q->iobase; in fsl_qspi_default_setup()
731 ret = clk_set_rate(q->clk, 66000000); in fsl_qspi_default_setup()
770 q->iobase + QUADSPI_BFGENCR); in fsl_qspi_default_setup()
773 QUADSPI_BUF3CR_ADATSZ(q->devtype_data->ahb_buf_size / 8), in fsl_qspi_default_setup()
777 addr_offset = q->memmap_phy; in fsl_qspi_default_setup()
786 qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset, in fsl_qspi_default_setup()
788 qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset, in fsl_qspi_default_setup()
790 qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset, in fsl_qspi_default_setup()
792 qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset, in fsl_qspi_default_setup()
795 q->selected = -1; in fsl_qspi_default_setup()
802 qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR); in fsl_qspi_default_setup()
805 qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); in fsl_qspi_default_setup()
812 struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); in fsl_qspi_get_name()
813 struct device *dev = &mem->spi->dev; in fsl_qspi_get_name()
818 * mtd/spi-nor/fsl-quadspi.c, we set a custom name derived from the in fsl_qspi_get_name()
821 if (of_get_available_child_count(q->dev->of_node) == 1) in fsl_qspi_get_name()
822 return dev_name(q->dev); in fsl_qspi_get_name()
825 "%s-%d", dev_name(q->dev), in fsl_qspi_get_name()
826 spi_get_chipselect(mem->spi, 0)); in fsl_qspi_get_name()
830 return ERR_PTR(-ENOMEM); in fsl_qspi_get_name()
852 qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); in fsl_qspi_cleanup()
853 qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER); in fsl_qspi_cleanup()
857 mutex_destroy(&q->lock); in fsl_qspi_cleanup()
863 struct device *dev = &pdev->dev; in fsl_qspi_probe()
864 struct device_node *np = dev->of_node; in fsl_qspi_probe()
869 ctlr = spi_alloc_host(&pdev->dev, sizeof(*q)); in fsl_qspi_probe()
871 return -ENOMEM; in fsl_qspi_probe()
873 ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | in fsl_qspi_probe()
877 q->dev = dev; in fsl_qspi_probe()
878 q->devtype_data = of_device_get_match_data(dev); in fsl_qspi_probe()
879 if (!q->devtype_data) { in fsl_qspi_probe()
880 ret = -ENODEV; in fsl_qspi_probe()
887 q->iobase = devm_platform_ioremap_resource_byname(pdev, "QuadSPI"); in fsl_qspi_probe()
888 if (IS_ERR(q->iobase)) { in fsl_qspi_probe()
889 ret = PTR_ERR(q->iobase); in fsl_qspi_probe()
894 "QuadSPI-memory"); in fsl_qspi_probe()
896 ret = -EINVAL; in fsl_qspi_probe()
899 q->memmap_phy = res->start; in fsl_qspi_probe()
901 q->ahb_addr = devm_ioremap(dev, q->memmap_phy, in fsl_qspi_probe()
902 (q->devtype_data->ahb_buf_size * 4)); in fsl_qspi_probe()
903 if (!q->ahb_addr) { in fsl_qspi_probe()
904 ret = -ENOMEM; in fsl_qspi_probe()
909 q->clk_en = devm_clk_get(dev, "qspi_en"); in fsl_qspi_probe()
910 if (IS_ERR(q->clk_en)) { in fsl_qspi_probe()
911 ret = PTR_ERR(q->clk_en); in fsl_qspi_probe()
915 q->clk = devm_clk_get(dev, "qspi"); in fsl_qspi_probe()
916 if (IS_ERR(q->clk)) { in fsl_qspi_probe()
917 ret = PTR_ERR(q->clk); in fsl_qspi_probe()
933 fsl_qspi_irq_handler, 0, pdev->name, q); in fsl_qspi_probe()
939 mutex_init(&q->lock); in fsl_qspi_probe()
941 ctlr->bus_num = -1; in fsl_qspi_probe()
942 ctlr->num_chipselect = 4; in fsl_qspi_probe()
943 ctlr->mem_ops = &fsl_qspi_mem_ops; in fsl_qspi_probe()
944 ctlr->mem_caps = &fsl_qspi_mem_caps; in fsl_qspi_probe()
948 ctlr->dev.of_node = np; in fsl_qspi_probe()
985 { .compatible = "fsl,vf610-qspi", .data = &vybrid_data, },
986 { .compatible = "fsl,imx6sx-qspi", .data = &imx6sx_data, },
987 { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, },
988 { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, },
989 { .compatible = "fsl,ls1021a-qspi", .data = &ls1021a_data, },
990 { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, },
1002 .name = "fsl-quadspi",