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()
527 unsigned long rate = spi->max_speed_hz; in fsl_qspi_select_mem()
530 if (q->selected == spi_get_chipselect(spi, 0)) in fsl_qspi_select_mem()
538 ret = clk_set_rate(q->clk, rate); in fsl_qspi_select_mem()
546 q->selected = spi_get_chipselect(spi, 0); in fsl_qspi_select_mem()
553 memcpy_fromio(op->data.buf.in, in fsl_qspi_read_ahb()
554 q->ahb_addr + q->selected * q->devtype_data->ahb_buf_size, in fsl_qspi_read_ahb()
555 op->data.nbytes); in fsl_qspi_read_ahb()
561 void __iomem *base = q->iobase; in fsl_qspi_fill_txfifo()
565 for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) { in fsl_qspi_fill_txfifo()
566 memcpy(&val, op->data.buf.out + i, 4); in fsl_qspi_fill_txfifo()
571 if (i < op->data.nbytes) { in fsl_qspi_fill_txfifo()
572 memcpy(&val, op->data.buf.out + i, op->data.nbytes - i); in fsl_qspi_fill_txfifo()
578 for (i = op->data.nbytes; i < 16; i += 4) in fsl_qspi_fill_txfifo()
586 void __iomem *base = q->iobase; in fsl_qspi_read_rxfifo()
588 u8 *buf = op->data.buf.in; in fsl_qspi_read_rxfifo()
591 for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) { in fsl_qspi_read_rxfifo()
597 if (i < op->data.nbytes) { in fsl_qspi_read_rxfifo()
600 memcpy(buf + i, &val, op->data.nbytes - i); in fsl_qspi_read_rxfifo()
606 void __iomem *base = q->iobase; in fsl_qspi_do_op()
609 init_completion(&q->c); in fsl_qspi_do_op()
616 qspi_writel(q, op->data.nbytes | QUADSPI_IPCR_SEQID(SEQID_LUT), in fsl_qspi_do_op()
620 if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) in fsl_qspi_do_op()
621 err = -ETIMEDOUT; in fsl_qspi_do_op()
623 if (!err && op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN) in fsl_qspi_do_op()
634 if (!q->devtype_data->little_endian) in fsl_qspi_readl_poll_tout()
643 struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); in fsl_qspi_exec_op()
644 void __iomem *base = q->iobase; in fsl_qspi_exec_op()
647 int invalid_mstrid = q->devtype_data->invalid_mstrid; in fsl_qspi_exec_op()
649 mutex_lock(&q->lock); in fsl_qspi_exec_op()
655 fsl_qspi_select_mem(q, mem->spi); in fsl_qspi_exec_op()
658 addr_offset = q->memmap_phy; in fsl_qspi_exec_op()
661 q->selected * q->devtype_data->ahb_buf_size + addr_offset, in fsl_qspi_exec_op()
682 if (op->data.nbytes > (q->devtype_data->rxfifo - 4) && in fsl_qspi_exec_op()
683 op->data.dir == SPI_MEM_DATA_IN) { in fsl_qspi_exec_op()
689 if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) in fsl_qspi_exec_op()
698 mutex_unlock(&q->lock); in fsl_qspi_exec_op()
705 struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); in fsl_qspi_adjust_op_size()
707 if (op->data.dir == SPI_MEM_DATA_OUT) { in fsl_qspi_adjust_op_size()
708 if (op->data.nbytes > q->devtype_data->txfifo) in fsl_qspi_adjust_op_size()
709 op->data.nbytes = q->devtype_data->txfifo; in fsl_qspi_adjust_op_size()
711 if (op->data.nbytes > q->devtype_data->ahb_buf_size) in fsl_qspi_adjust_op_size()
712 op->data.nbytes = q->devtype_data->ahb_buf_size; in fsl_qspi_adjust_op_size()
713 else if (op->data.nbytes > (q->devtype_data->rxfifo - 4)) in fsl_qspi_adjust_op_size()
714 op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8); in fsl_qspi_adjust_op_size()
722 void __iomem *base = q->iobase; in fsl_qspi_default_setup()
730 ret = clk_set_rate(q->clk, 66000000); in fsl_qspi_default_setup()
769 q->iobase + QUADSPI_BFGENCR); in fsl_qspi_default_setup()
772 QUADSPI_BUF3CR_ADATSZ(q->devtype_data->ahb_buf_size / 8), in fsl_qspi_default_setup()
776 addr_offset = q->memmap_phy; in fsl_qspi_default_setup()
785 qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset, in fsl_qspi_default_setup()
787 qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset, in fsl_qspi_default_setup()
789 qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset, in fsl_qspi_default_setup()
791 qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset, in fsl_qspi_default_setup()
794 q->selected = -1; in fsl_qspi_default_setup()
801 qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR); in fsl_qspi_default_setup()
804 qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); in fsl_qspi_default_setup()
811 struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); in fsl_qspi_get_name()
812 struct device *dev = &mem->spi->dev; in fsl_qspi_get_name()
817 * mtd/spi-nor/fsl-quadspi.c, we set a custom name derived from the in fsl_qspi_get_name()
820 if (of_get_available_child_count(q->dev->of_node) == 1) in fsl_qspi_get_name()
821 return dev_name(q->dev); in fsl_qspi_get_name()
824 "%s-%d", dev_name(q->dev), in fsl_qspi_get_name()
825 spi_get_chipselect(mem->spi, 0)); in fsl_qspi_get_name()
829 return ERR_PTR(-ENOMEM); in fsl_qspi_get_name()
845 struct device *dev = &pdev->dev; in fsl_qspi_probe()
846 struct device_node *np = dev->of_node; in fsl_qspi_probe()
851 ctlr = spi_alloc_host(&pdev->dev, sizeof(*q)); in fsl_qspi_probe()
853 return -ENOMEM; in fsl_qspi_probe()
855 ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | in fsl_qspi_probe()
859 q->dev = dev; in fsl_qspi_probe()
860 q->devtype_data = of_device_get_match_data(dev); in fsl_qspi_probe()
861 if (!q->devtype_data) { in fsl_qspi_probe()
862 ret = -ENODEV; in fsl_qspi_probe()
869 q->iobase = devm_platform_ioremap_resource_byname(pdev, "QuadSPI"); in fsl_qspi_probe()
870 if (IS_ERR(q->iobase)) { in fsl_qspi_probe()
871 ret = PTR_ERR(q->iobase); in fsl_qspi_probe()
876 "QuadSPI-memory"); in fsl_qspi_probe()
878 ret = -EINVAL; in fsl_qspi_probe()
881 q->memmap_phy = res->start; in fsl_qspi_probe()
883 q->ahb_addr = devm_ioremap(dev, q->memmap_phy, in fsl_qspi_probe()
884 (q->devtype_data->ahb_buf_size * 4)); in fsl_qspi_probe()
885 if (!q->ahb_addr) { in fsl_qspi_probe()
886 ret = -ENOMEM; in fsl_qspi_probe()
891 q->clk_en = devm_clk_get(dev, "qspi_en"); in fsl_qspi_probe()
892 if (IS_ERR(q->clk_en)) { in fsl_qspi_probe()
893 ret = PTR_ERR(q->clk_en); in fsl_qspi_probe()
897 q->clk = devm_clk_get(dev, "qspi"); in fsl_qspi_probe()
898 if (IS_ERR(q->clk)) { in fsl_qspi_probe()
899 ret = PTR_ERR(q->clk); in fsl_qspi_probe()
915 fsl_qspi_irq_handler, 0, pdev->name, q); in fsl_qspi_probe()
921 mutex_init(&q->lock); in fsl_qspi_probe()
923 ctlr->bus_num = -1; in fsl_qspi_probe()
924 ctlr->num_chipselect = 4; in fsl_qspi_probe()
925 ctlr->mem_ops = &fsl_qspi_mem_ops; in fsl_qspi_probe()
929 ctlr->dev.of_node = np; in fsl_qspi_probe()
938 mutex_destroy(&q->lock); in fsl_qspi_probe()
955 qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); in fsl_qspi_remove()
956 qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER); in fsl_qspi_remove()
960 mutex_destroy(&q->lock); in fsl_qspi_remove()
978 { .compatible = "fsl,vf610-qspi", .data = &vybrid_data, },
979 { .compatible = "fsl,imx6sx-qspi", .data = &imx6sx_data, },
980 { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, },
981 { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, },
982 { .compatible = "fsl,ls1021a-qspi", .data = &ls1021a_data, },
983 { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, },
995 .name = "fsl-quadspi",