Lines Matching +full:mx25f0a +full:- +full:spi
1 // SPDX-License-Identifier: GPL-2.0
17 #include <linux/spi/spi.h>
18 #include <linux/spi/spi-mem.h>
72 #define OP_CMD_BYTES(x) (((x) - 1) << 13)
181 ret = clk_prepare_enable(mxic->send_clk); in mxic_spi_clk_enable()
185 ret = clk_prepare_enable(mxic->send_dly_clk); in mxic_spi_clk_enable()
192 clk_disable_unprepare(mxic->send_clk); in mxic_spi_clk_enable()
199 clk_disable_unprepare(mxic->send_clk); in mxic_spi_clk_disable()
200 clk_disable_unprepare(mxic->send_dly_clk); in mxic_spi_clk_disable()
209 mxic->regs + IDLY_CODE(0)); in mxic_spi_set_input_delay_dqs()
214 mxic->regs + IDLY_CODE(1)); in mxic_spi_set_input_delay_dqs()
221 ret = clk_set_rate(mxic->send_clk, freq); in mxic_spi_clk_setup()
225 ret = clk_set_rate(mxic->send_dly_clk, freq); in mxic_spi_clk_setup()
236 * Phase degree = 360 * freq * output-delay in mxic_spi_clk_setup()
237 * where output-delay is a constant value 1 ns in FPGA. in mxic_spi_clk_setup()
243 ret = clk_set_phase(mxic->send_dly_clk, 9 * freq / 25000000); in mxic_spi_clk_setup()
254 if (mxic->cur_speed_hz == freq) in mxic_spi_set_freq()
266 mxic->cur_speed_hz = freq; in mxic_spi_set_freq()
273 writel(0, mxic->regs + DATA_STROB); in mxic_spi_hw_init()
274 writel(INT_STS_ALL, mxic->regs + INT_STS_EN); in mxic_spi_hw_init()
275 writel(0, mxic->regs + HC_EN); in mxic_spi_hw_init()
276 writel(0, mxic->regs + LRD_CFG); in mxic_spi_hw_init()
277 writel(0, mxic->regs + LRD_CTRL); in mxic_spi_hw_init()
280 mxic->regs + HC_CFG); in mxic_spi_hw_init()
289 unsigned int nbytes = len - pos; in mxic_spi_data_xfer()
300 ret = readl_poll_timeout(mxic->regs + INT_STS, sts, in mxic_spi_data_xfer()
305 writel(data, mxic->regs + TXD(nbytes % 4)); in mxic_spi_data_xfer()
307 ret = readl_poll_timeout(mxic->regs + INT_STS, sts, in mxic_spi_data_xfer()
312 ret = readl_poll_timeout(mxic->regs + INT_STS, sts, in mxic_spi_data_xfer()
318 data = readl(mxic->regs + RXD); in mxic_spi_data_xfer()
320 data >>= (8 * (4 - nbytes)); in mxic_spi_data_xfer()
323 WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY); in mxic_spi_data_xfer()
334 if (op->data.buswidth > 4 || op->addr.buswidth > 4 || in mxic_spi_mem_supports_op()
335 op->dummy.buswidth > 4 || op->cmd.buswidth > 4) in mxic_spi_mem_supports_op()
338 if (op->data.nbytes && op->dummy.nbytes && in mxic_spi_mem_supports_op()
339 op->data.buswidth != op->dummy.buswidth) in mxic_spi_mem_supports_op()
342 if (op->addr.nbytes > 7) in mxic_spi_mem_supports_op()
351 struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master); in mxic_spi_mem_exec_op()
355 u8 opcode = op->cmd.opcode; in mxic_spi_mem_exec_op()
357 ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz); in mxic_spi_mem_exec_op()
361 if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD)) in mxic_spi_mem_exec_op()
363 else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL)) in mxic_spi_mem_exec_op()
367 HC_CFG_TYPE(mem->spi->chip_select, HC_CFG_TYPE_SPI_NOR) | in mxic_spi_mem_exec_op()
368 HC_CFG_SLV_ACT(mem->spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1) | in mxic_spi_mem_exec_op()
370 mxic->regs + HC_CFG); in mxic_spi_mem_exec_op()
371 writel(HC_EN_BIT, mxic->regs + HC_EN); in mxic_spi_mem_exec_op()
373 ss_ctrl = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1); in mxic_spi_mem_exec_op()
375 if (op->addr.nbytes) in mxic_spi_mem_exec_op()
376 ss_ctrl |= OP_ADDR_BYTES(op->addr.nbytes) | in mxic_spi_mem_exec_op()
377 OP_ADDR_BUSW(fls(op->addr.buswidth) - 1); in mxic_spi_mem_exec_op()
379 if (op->dummy.nbytes) in mxic_spi_mem_exec_op()
380 ss_ctrl |= OP_DUMMY_CYC(op->dummy.nbytes); in mxic_spi_mem_exec_op()
382 if (op->data.nbytes) { in mxic_spi_mem_exec_op()
383 ss_ctrl |= OP_DATA_BUSW(fls(op->data.buswidth) - 1); in mxic_spi_mem_exec_op()
384 if (op->data.dir == SPI_MEM_DATA_IN) in mxic_spi_mem_exec_op()
388 writel(ss_ctrl, mxic->regs + SS_CTRL(mem->spi->chip_select)); in mxic_spi_mem_exec_op()
390 writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT, in mxic_spi_mem_exec_op()
391 mxic->regs + HC_CFG); in mxic_spi_mem_exec_op()
397 for (i = 0; i < op->addr.nbytes; i++) in mxic_spi_mem_exec_op()
398 addr[i] = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); in mxic_spi_mem_exec_op()
400 ret = mxic_spi_data_xfer(mxic, addr, NULL, op->addr.nbytes); in mxic_spi_mem_exec_op()
404 ret = mxic_spi_data_xfer(mxic, NULL, NULL, op->dummy.nbytes); in mxic_spi_mem_exec_op()
409 op->data.dir == SPI_MEM_DATA_OUT ? in mxic_spi_mem_exec_op()
410 op->data.buf.out : NULL, in mxic_spi_mem_exec_op()
411 op->data.dir == SPI_MEM_DATA_IN ? in mxic_spi_mem_exec_op()
412 op->data.buf.in : NULL, in mxic_spi_mem_exec_op()
413 op->data.nbytes); in mxic_spi_mem_exec_op()
416 writel(readl(mxic->regs + HC_CFG) & ~HC_CFG_MAN_CS_ASSERT, in mxic_spi_mem_exec_op()
417 mxic->regs + HC_CFG); in mxic_spi_mem_exec_op()
418 writel(0, mxic->regs + HC_EN); in mxic_spi_mem_exec_op()
428 static void mxic_spi_set_cs(struct spi_device *spi, bool lvl) in mxic_spi_set_cs() argument
430 struct mxic_spi *mxic = spi_master_get_devdata(spi->master); in mxic_spi_set_cs()
433 writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_EN, in mxic_spi_set_cs()
434 mxic->regs + HC_CFG); in mxic_spi_set_cs()
435 writel(HC_EN_BIT, mxic->regs + HC_EN); in mxic_spi_set_cs()
436 writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT, in mxic_spi_set_cs()
437 mxic->regs + HC_CFG); in mxic_spi_set_cs()
439 writel(readl(mxic->regs + HC_CFG) & ~HC_CFG_MAN_CS_ASSERT, in mxic_spi_set_cs()
440 mxic->regs + HC_CFG); in mxic_spi_set_cs()
441 writel(0, mxic->regs + HC_EN); in mxic_spi_set_cs()
446 struct spi_device *spi, in mxic_spi_transfer_one() argument
453 if (t->rx_buf && t->tx_buf) { in mxic_spi_transfer_one()
454 if (((spi->mode & SPI_TX_QUAD) && in mxic_spi_transfer_one()
455 !(spi->mode & SPI_RX_QUAD)) || in mxic_spi_transfer_one()
456 ((spi->mode & SPI_TX_DUAL) && in mxic_spi_transfer_one()
457 !(spi->mode & SPI_RX_DUAL))) in mxic_spi_transfer_one()
458 return -ENOTSUPP; in mxic_spi_transfer_one()
461 ret = mxic_spi_set_freq(mxic, t->speed_hz); in mxic_spi_transfer_one()
465 if (t->tx_buf) { in mxic_spi_transfer_one()
466 if (spi->mode & SPI_TX_QUAD) in mxic_spi_transfer_one()
468 else if (spi->mode & SPI_TX_DUAL) in mxic_spi_transfer_one()
470 } else if (t->rx_buf) { in mxic_spi_transfer_one()
471 if (spi->mode & SPI_RX_QUAD) in mxic_spi_transfer_one()
473 else if (spi->mode & SPI_RX_DUAL) in mxic_spi_transfer_one()
478 OP_DATA_BUSW(busw) | (t->rx_buf ? OP_READ : 0), in mxic_spi_transfer_one()
479 mxic->regs + SS_CTRL(0)); in mxic_spi_transfer_one()
481 ret = mxic_spi_data_xfer(mxic, t->tx_buf, t->rx_buf, t->len); in mxic_spi_transfer_one()
496 clk_disable_unprepare(mxic->ps_clk); in mxic_spi_runtime_suspend()
507 ret = clk_prepare_enable(mxic->ps_clk); in mxic_spi_runtime_resume()
528 master = devm_spi_alloc_master(&pdev->dev, sizeof(struct mxic_spi)); in mxic_spi_probe()
530 return -ENOMEM; in mxic_spi_probe()
536 master->dev.of_node = pdev->dev.of_node; in mxic_spi_probe()
538 mxic->ps_clk = devm_clk_get(&pdev->dev, "ps_clk"); in mxic_spi_probe()
539 if (IS_ERR(mxic->ps_clk)) in mxic_spi_probe()
540 return PTR_ERR(mxic->ps_clk); in mxic_spi_probe()
542 mxic->send_clk = devm_clk_get(&pdev->dev, "send_clk"); in mxic_spi_probe()
543 if (IS_ERR(mxic->send_clk)) in mxic_spi_probe()
544 return PTR_ERR(mxic->send_clk); in mxic_spi_probe()
546 mxic->send_dly_clk = devm_clk_get(&pdev->dev, "send_dly_clk"); in mxic_spi_probe()
547 if (IS_ERR(mxic->send_dly_clk)) in mxic_spi_probe()
548 return PTR_ERR(mxic->send_dly_clk); in mxic_spi_probe()
551 mxic->regs = devm_ioremap_resource(&pdev->dev, res); in mxic_spi_probe()
552 if (IS_ERR(mxic->regs)) in mxic_spi_probe()
553 return PTR_ERR(mxic->regs); in mxic_spi_probe()
555 pm_runtime_enable(&pdev->dev); in mxic_spi_probe()
556 master->auto_runtime_pm = true; in mxic_spi_probe()
558 master->num_chipselect = 1; in mxic_spi_probe()
559 master->mem_ops = &mxic_spi_mem_ops; in mxic_spi_probe()
561 master->set_cs = mxic_spi_set_cs; in mxic_spi_probe()
562 master->transfer_one = mxic_spi_transfer_one; in mxic_spi_probe()
563 master->bits_per_word_mask = SPI_BPW_MASK(8); in mxic_spi_probe()
564 master->mode_bits = SPI_CPOL | SPI_CPHA | in mxic_spi_probe()
572 dev_err(&pdev->dev, "spi_register_master failed\n"); in mxic_spi_probe()
573 pm_runtime_disable(&pdev->dev); in mxic_spi_probe()
583 pm_runtime_disable(&pdev->dev); in mxic_spi_remove()
590 { .compatible = "mxicy,mx25f0a-spi", },
599 .name = "mxic-spi",
607 MODULE_DESCRIPTION("MX25F0A SPI controller driver");