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:
43 #include <linux/spi/spi-mem.h>
159 #define LUT_PAD(x) (fls(x) - 1)
165 * ---------------------------------------------------
167 * ---------------------------------------------------
280 return q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN; in needs_swap_endian()
285 return q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK; in needs_4x_clock()
290 return q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890; in needs_fill_txfifo()
295 return q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618; in needs_wakeup_wait_mode()
300 return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL); in needs_amba_base_offset()
305 return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING; in needs_tdh_setting()
309 * An IC bug makes it necessary to rearrange the 32-bit data.
318 * R/W functions for big- or little-endian registers:
319 * The QSPI controller's endianness is independent of
321 * core is little-endian the QSPI controller can use
322 * big-endian or little-endian.
326 if (q->devtype_data->little_endian) in qspi_writel()
334 if (q->devtype_data->little_endian) in qspi_readl()
346 reg = qspi_readl(q, q->iobase + QUADSPI_FR); in fsl_qspi_irq_handler()
347 qspi_writel(q, reg, q->iobase + QUADSPI_FR); in fsl_qspi_irq_handler()
350 complete(&q->c); in fsl_qspi_irq_handler()
352 dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", 0, reg); in fsl_qspi_irq_handler()
365 return -ENOTSUPP; in fsl_qspi_check_buswidth()
371 struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); in fsl_qspi_supports_op()
374 ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth); in fsl_qspi_supports_op()
376 if (op->addr.nbytes) in fsl_qspi_supports_op()
377 ret |= fsl_qspi_check_buswidth(q, op->addr.buswidth); in fsl_qspi_supports_op()
379 if (op->dummy.nbytes) in fsl_qspi_supports_op()
380 ret |= fsl_qspi_check_buswidth(q, op->dummy.buswidth); in fsl_qspi_supports_op()
382 if (op->data.nbytes) in fsl_qspi_supports_op()
383 ret |= fsl_qspi_check_buswidth(q, op->data.buswidth); in fsl_qspi_supports_op()
392 if (op->addr.nbytes + in fsl_qspi_supports_op()
393 (op->dummy.nbytes ? 1:0) + in fsl_qspi_supports_op()
394 (op->data.nbytes ? 1:0) > 6) in fsl_qspi_supports_op()
398 if (op->dummy.nbytes && in fsl_qspi_supports_op()
399 (op->dummy.nbytes * 8 / op->dummy.buswidth > 64)) in fsl_qspi_supports_op()
403 if (op->data.dir == SPI_MEM_DATA_IN && in fsl_qspi_supports_op()
404 (op->data.nbytes > q->devtype_data->ahb_buf_size || in fsl_qspi_supports_op()
405 (op->data.nbytes > q->devtype_data->rxfifo - 4 && in fsl_qspi_supports_op()
406 !IS_ALIGNED(op->data.nbytes, 8)))) in fsl_qspi_supports_op()
409 if (op->data.dir == SPI_MEM_DATA_OUT && in fsl_qspi_supports_op()
410 op->data.nbytes > q->devtype_data->txfifo) in fsl_qspi_supports_op()
419 void __iomem *base = q->iobase; in fsl_qspi_prepare_lut()
423 lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), in fsl_qspi_prepare_lut()
424 op->cmd.opcode); in fsl_qspi_prepare_lut()
431 for (i = 0; i < op->addr.nbytes; i++) { in fsl_qspi_prepare_lut()
432 u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); in fsl_qspi_prepare_lut()
435 LUT_PAD(op->addr.buswidth), in fsl_qspi_prepare_lut()
440 if (op->dummy.nbytes) { in fsl_qspi_prepare_lut()
442 LUT_PAD(op->dummy.buswidth), in fsl_qspi_prepare_lut()
443 op->dummy.nbytes * 8 / in fsl_qspi_prepare_lut()
444 op->dummy.buswidth); in fsl_qspi_prepare_lut()
448 if (op->data.nbytes) { in fsl_qspi_prepare_lut()
450 op->data.dir == SPI_MEM_DATA_IN ? in fsl_qspi_prepare_lut()
452 LUT_PAD(op->data.buswidth), in fsl_qspi_prepare_lut()
460 qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); in fsl_qspi_prepare_lut()
461 qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); in fsl_qspi_prepare_lut()
468 qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); in fsl_qspi_prepare_lut()
469 qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); in fsl_qspi_prepare_lut()
476 ret = clk_prepare_enable(q->clk_en); in fsl_qspi_clk_prep_enable()
480 ret = clk_prepare_enable(q->clk); in fsl_qspi_clk_prep_enable()
482 clk_disable_unprepare(q->clk_en); in fsl_qspi_clk_prep_enable()
487 cpu_latency_qos_add_request(&q->pm_qos_req, 0); in fsl_qspi_clk_prep_enable()
495 cpu_latency_qos_remove_request(&q->pm_qos_req); in fsl_qspi_clk_disable_unprep()
497 clk_disable_unprepare(q->clk); in fsl_qspi_clk_disable_unprep()
498 clk_disable_unprepare(q->clk_en); in fsl_qspi_clk_disable_unprep()
512 reg = qspi_readl(q, q->iobase + QUADSPI_MCR); in fsl_qspi_invalidate()
514 qspi_writel(q, reg, q->iobase + QUADSPI_MCR); in fsl_qspi_invalidate()
523 qspi_writel(q, reg, q->iobase + QUADSPI_MCR); in fsl_qspi_invalidate()
528 unsigned long rate = spi->max_speed_hz; in fsl_qspi_select_mem()
531 if (q->selected == spi->chip_select) in fsl_qspi_select_mem()
539 ret = clk_set_rate(q->clk, rate); in fsl_qspi_select_mem()
547 q->selected = spi->chip_select; 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->master); 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); 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->master); 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->master); 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 mem->spi->chip_select); in fsl_qspi_get_name()
830 return ERR_PTR(-ENOMEM); in fsl_qspi_get_name()
846 struct device *dev = &pdev->dev; in fsl_qspi_probe()
847 struct device_node *np = dev->of_node; in fsl_qspi_probe()
852 ctlr = spi_alloc_master(&pdev->dev, sizeof(*q)); in fsl_qspi_probe()
854 return -ENOMEM; in fsl_qspi_probe()
856 ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | in fsl_qspi_probe()
860 q->dev = dev; in fsl_qspi_probe()
861 q->devtype_data = of_device_get_match_data(dev); in fsl_qspi_probe()
862 if (!q->devtype_data) { in fsl_qspi_probe()
863 ret = -ENODEV; in fsl_qspi_probe()
870 q->iobase = devm_platform_ioremap_resource_byname(pdev, "QuadSPI"); in fsl_qspi_probe()
871 if (IS_ERR(q->iobase)) { in fsl_qspi_probe()
872 ret = PTR_ERR(q->iobase); in fsl_qspi_probe()
877 "QuadSPI-memory"); in fsl_qspi_probe()
879 ret = -EINVAL; in fsl_qspi_probe()
882 q->memmap_phy = res->start; in fsl_qspi_probe()
884 q->ahb_addr = devm_ioremap(dev, q->memmap_phy, in fsl_qspi_probe()
885 (q->devtype_data->ahb_buf_size * 4)); in fsl_qspi_probe()
886 if (!q->ahb_addr) { in fsl_qspi_probe()
887 ret = -ENOMEM; in fsl_qspi_probe()
892 q->clk_en = devm_clk_get(dev, "qspi_en"); in fsl_qspi_probe()
893 if (IS_ERR(q->clk_en)) { in fsl_qspi_probe()
894 ret = PTR_ERR(q->clk_en); in fsl_qspi_probe()
898 q->clk = devm_clk_get(dev, "qspi"); in fsl_qspi_probe()
899 if (IS_ERR(q->clk)) { in fsl_qspi_probe()
900 ret = PTR_ERR(q->clk); in fsl_qspi_probe()
916 fsl_qspi_irq_handler, 0, pdev->name, q); in fsl_qspi_probe()
922 mutex_init(&q->lock); in fsl_qspi_probe()
924 ctlr->bus_num = -1; in fsl_qspi_probe()
925 ctlr->num_chipselect = 4; in fsl_qspi_probe()
926 ctlr->mem_ops = &fsl_qspi_mem_ops; in fsl_qspi_probe()
930 ctlr->dev.of_node = np; in fsl_qspi_probe()
939 mutex_destroy(&q->lock); in fsl_qspi_probe()
956 qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); in fsl_qspi_remove()
957 qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER); in fsl_qspi_remove()
961 mutex_destroy(&q->lock); in fsl_qspi_remove()
981 { .compatible = "fsl,vf610-qspi", .data = &vybrid_data, },
982 { .compatible = "fsl,imx6sx-qspi", .data = &imx6sx_data, },
983 { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, },
984 { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, },
985 { .compatible = "fsl,ls1021a-qspi", .data = &ls1021a_data, },
986 { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, },
998 .name = "fsl-quadspi",