Lines Matching +full:cs +full:- +full:setup +full:- +full:time

4  * SPDX-License-Identifier: Apache-2.0
20 #include <zephyr/dt-bindings/clock/mchp_xec_pcr.h>
21 #include <zephyr/dt-bindings/interrupt-controller/mchp-xec-ecia.h>
35 * data bytes will be left shifted by 1. Work-around for SPI Mode 3 is
94 /* Device run time data */
123 return -ETIMEDOUT; in xec_qmspi_spin_yield()
133 * Some QMSPI timing register may be modified by the Boot-ROM OTP
144 taps[0] = regs->TM_TAPS; in qmspi_reset()
145 taps[1] = regs->TM_TAPS_ADJ; in qmspi_reset()
146 taps[2] = regs->TM_TAPS_CTRL; in qmspi_reset()
147 malt1 = regs->MODE_ALT1; in qmspi_reset()
148 cstm = regs->CSTM; in qmspi_reset()
149 mode = regs->MODE; in qmspi_reset()
150 regs->MODE = MCHP_QMSPI_M_SRST; in qmspi_reset()
151 while (regs->MODE & MCHP_QMSPI_M_SRST) { in qmspi_reset()
155 cnt--; in qmspi_reset()
157 regs->MODE = 0; in qmspi_reset()
158 regs->MODE = mode & ~MCHP_QMSPI_M_ACTIVATE; in qmspi_reset()
159 regs->CSTM = cstm; in qmspi_reset()
160 regs->MODE_ALT1 = malt1; in qmspi_reset()
161 regs->TM_TAPS = taps[0]; in qmspi_reset()
162 regs->TM_TAPS_ADJ = taps[1]; in qmspi_reset()
163 regs->TM_TAPS_CTRL = taps[2]; in qmspi_reset()
168 struct spi_qmspi_data *qdata = dev->data; in qmspi_encoded_fdiv()
174 return (qdata->base_freq_hz / freq_hz); in qmspi_encoded_fdiv()
182 * been expanded to a 16-bit field encoded as:
192 if (qdata->base_freq_hz) { in qmspi_set_frequency()
193 clk = qdata->base_freq_hz; in qmspi_set_frequency()
203 regs->MODE = ((regs->MODE & ~(MCHP_QMSPI_M_FDIV_MASK)) | in qmspi_set_frequency()
210 qdata->spi_freq_hz = clk / fdiv; in qmspi_set_frequency()
261 if (qdata->spi_freq_hz >= MHZ(48)) { in qmspi_set_signalling_mode()
266 regs->MODE = (regs->MODE & ~(MCHP_QMSPI_M_SIG_MASK)) in qmspi_set_signalling_mode()
279 switch (config->operation & SPI_LINES_MASK) { in encode_lines()
302 switch (config->operation & SPI_LINES_MASK) { in npins_from_spi_config()
315 if (config->operation & (SPI_TRANSFER_LSB | SPI_OP_MODE_SLAVE | SPI_MODE_LOOP)) { in spi_feature_support()
317 return -ENOTSUP; in spi_feature_support()
320 if (config->operation & SPI_CS_ACTIVE_HIGH) { in spi_feature_support()
321 LOG_ERR("CS active high not supported"); in spi_feature_support()
322 return -ENOTSUP; in spi_feature_support()
325 if (config->operation & SPI_LOCK_ON) { in spi_feature_support()
327 return -ENOTSUP; in spi_feature_support()
330 if (SPI_WORD_SIZE_GET(config->operation) != 8) { in spi_feature_support()
332 return -ENOTSUP; in spi_feature_support()
342 * if SPI extended mode is enabled at build time. User must
348 const struct spi_qmspi_config *cfg = dev->config; in qmspi_configure()
349 struct spi_qmspi_data *qdata = dev->data; in qmspi_configure()
350 struct qmspi_regs *regs = cfg->regs; in qmspi_configure()
355 return -EINVAL; in qmspi_configure()
358 if (spi_context_configured(&qdata->ctx, config)) { in qmspi_configure()
362 qmspi_set_frequency(qdata, regs, config->frequency); in qmspi_configure()
374 return -ENOTSUP; in qmspi_configure()
376 qdata->np = npins_from_spi_config(config); in qmspi_configure()
379 qdata->np = 1u; in qmspi_configure()
381 regs->CTRL = smode; in qmspi_configure()
384 if ((config->operation & SPI_MODE_CPHA) != 0U) { in qmspi_configure()
388 if ((config->operation & SPI_MODE_CPOL) != 0U) { in qmspi_configure()
395 smode = regs->MODE & ~(MCHP_QMSPI_M_CS_MASK); in qmspi_configure()
396 if (cfg->chip_sel == 0) { in qmspi_configure()
401 regs->MODE = smode; in qmspi_configure()
404 regs->CSTM = cfg->cs_timing; in qmspi_configure()
405 regs->TM_TAPS_ADJ = cfg->taps_adj; in qmspi_configure()
408 regs->MODE_ALT1 = 0; in qmspi_configure()
409 if (cfg->cs1_freq) { in qmspi_configure()
410 uint32_t fdiv = qmspi_encoded_fdiv(dev, cfg->cs1_freq); in qmspi_configure()
412 regs->MODE_ALT1 = (fdiv << MCHP_QMSPI_MA1_CS1_CDIV_POS) & in qmspi_configure()
414 regs->MODE_ALT1 |= MCHP_QMSPI_MA1_CS1_CDIV_EN; in qmspi_configure()
417 qdata->ctx.config = config; in qmspi_configure()
419 regs->MODE |= MCHP_QMSPI_M_ACTIVATE; in qmspi_configure()
435 /* Common controller transfer initialziation using Local-DMA.
436 * Full-duplex: controller configured to transmit and receive simultaneouly.
437 * Half-duplex(dual/quad): User may only specify TX or RX buffer sets.
444 const struct spi_qmspi_config *devcfg = dev->config; in qmspi_xfr_cm_init()
445 struct spi_qmspi_data *qdata = dev->data; in qmspi_xfr_cm_init()
446 struct qmspi_regs *regs = devcfg->regs; in qmspi_xfr_cm_init()
448 regs->IEN = 0; in qmspi_xfr_cm_init()
449 regs->EXE = MCHP_QMSPI_EXE_CLR_FIFOS; in qmspi_xfr_cm_init()
450 regs->LDMA_RX_DESCR_BM = 0; in qmspi_xfr_cm_init()
451 regs->LDMA_TX_DESCR_BM = 0; in qmspi_xfr_cm_init()
452 regs->MODE &= ~(MCHP_QMSPI_M_LDMA_TX_EN | MCHP_QMSPI_M_LDMA_RX_EN); in qmspi_xfr_cm_init()
453 regs->STS = 0xffffffffu; in qmspi_xfr_cm_init()
454 regs->CTRL = encode_npins(qdata->np); in qmspi_xfr_cm_init()
456 qdata->qstatus = 0; in qmspi_xfr_cm_init()
459 if (qdata->np != 1) { in qmspi_xfr_cm_init()
461 LOG_ERR("Cannot specify both TX and RX buffers in half-duplex(dual/quad)"); in qmspi_xfr_cm_init()
462 return -EPROTONOSUPPORT; in qmspi_xfr_cm_init()
470 /* QMSPI Local-DMA transfer configuration:
472 * Requires caller to have checked that only one direction was setup
474 * Supports spi_buf's where data pointer is NULL and length non-zero.
475 * These buffers are used as TX tri-state I/O clock only generation or
478 * 2. If the SPI TX context has a non-zero length configure Local-DMA TX
482 * of clocks to generate with output line(s) tri-stated. NOTE: The controller
486 * based upon the number of output pins in the IOM field: full-duplex is one
490 * 3. If instead, the SPI RX context has a non-zero length configure Local-DMA
534 const struct spi_qmspi_config *devcfg = dev->config; in q_ldma_cfg()
535 struct spi_qmspi_data *qdata = dev->data; in q_ldma_cfg()
536 struct spi_context *ctx = &qdata->ctx; in q_ldma_cfg()
537 struct qmspi_regs *regs = devcfg->regs; in q_ldma_cfg()
542 regs->EXE = MCHP_QMSPI_EXE_CLR_FIFOS; in q_ldma_cfg()
543 regs->MODE &= ~(MCHP_QMSPI_M_LDMA_RX_EN | MCHP_QMSPI_M_LDMA_TX_EN); in q_ldma_cfg()
544 regs->LDRX[0].CTRL = 0; in q_ldma_cfg()
545 regs->LDRX[0].MSTART = 0; in q_ldma_cfg()
546 regs->LDRX[0].LEN = 0; in q_ldma_cfg()
547 regs->LDTX[0].CTRL = 0; in q_ldma_cfg()
548 regs->LDTX[0].MSTART = 0; in q_ldma_cfg()
549 regs->LDTX[0].LEN = 0; in q_ldma_cfg()
565 qdata->qunits = qunits; in q_ldma_cfg()
566 qdata->qxfru = qxfru; in q_ldma_cfg()
567 qdata->xfrlen = xfrlen; in q_ldma_cfg()
570 mstart = (uint32_t)ctx->tx_buf; in q_ldma_cfg()
574 regs->MODE |= MCHP_QMSPI_M_LDMA_TX_EN; in q_ldma_cfg()
575 regs->LDTX[0].LEN = xfrlen; in q_ldma_cfg()
576 regs->LDTX[0].MSTART = mstart; in q_ldma_cfg()
577 regs->LDTX[0].CTRL = ldctrl; in q_ldma_cfg()
581 mstart = (uint32_t)ctx->rx_buf; in q_ldma_cfg()
585 regs->MODE |= MCHP_QMSPI_M_LDMA_RX_EN; in q_ldma_cfg()
586 regs->LDRX[0].LEN = xfrlen; in q_ldma_cfg()
587 regs->LDRX[0].MSTART = mstart; in q_ldma_cfg()
588 regs->LDRX[0].CTRL = ldctrl; in q_ldma_cfg()
591 regs->CTRL = (regs->CTRL & 0x3u) | ctrl; in q_ldma_cfg()
597 * Initialize QMSPI controller for Local-DMA operation.
598 * Iterate over SPI context with non-zero TX or RX data lengths.
599 * 1. Configure QMSPI Control register and Local-DMA channel(s)
603 * 5. Hardware anomaly work-around: Poll with timeout QMSPI Local-DMA
608 * QMSPI to de-assert chip select.
616 const struct spi_qmspi_config *devcfg = dev->config; in qmspi_xfr_sync()
617 struct spi_qmspi_data *qdata = dev->data; in qmspi_xfr_sync()
618 struct spi_context *ctx = &qdata->ctx; in qmspi_xfr_sync()
619 struct qmspi_regs *regs = devcfg->regs; in qmspi_xfr_sync()
630 regs->STS = 0xffffffffu; in qmspi_xfr_sync()
631 regs->EXE = MCHP_QMSPI_EXE_START; in qmspi_xfr_sync()
634 uint32_t temp = regs->STS; in qmspi_xfr_sync()
637 temp = regs->STS; in qmspi_xfr_sync()
639 qdata->qstatus = temp; in qmspi_xfr_sync()
640 qdata->bufcnt_status = regs->BCNT_STS; in qmspi_xfr_sync()
641 qdata->rx_ldma_ctrl0 = regs->LDRX[0].CTRL; in qmspi_xfr_sync()
642 qdata->tx_ldma_ctrl0 = regs->LDTX[0].CTRL; in qmspi_xfr_sync()
646 qdata->qstatus = regs->STS; in qmspi_xfr_sync()
647 while (!(qdata->qstatus & MCHP_QMSPI_STS_DONE)) { in qmspi_xfr_sync()
650 regs->EXE = MCHP_QMSPI_EXE_STOP; in qmspi_xfr_sync()
651 return -ETIMEDOUT; in qmspi_xfr_sync()
653 qdata->qstatus = regs->STS; in qmspi_xfr_sync()
660 if (!(spi_cfg->operation & SPI_HOLD_ON_CS)) { in qmspi_xfr_sync()
661 regs->EXE = MCHP_QMSPI_EXE_STOP; in qmspi_xfr_sync()
677 const struct spi_qmspi_config *devcfg = dev->config; in qmspi_xfr_start_async()
678 struct spi_qmspi_data *qdata = dev->data; in qmspi_xfr_start_async()
679 struct qmspi_regs *regs = devcfg->regs; in qmspi_xfr_start_async()
687 qdata->xfr_len = q_ldma_cfg(dev); in qmspi_xfr_start_async()
688 if (!qdata->xfr_len) { in qmspi_xfr_start_async()
692 regs->STS = 0xffffffffu; in qmspi_xfr_start_async()
693 regs->EXE = MCHP_QMSPI_EXE_START; in qmspi_xfr_start_async()
694 regs->IEN = MCHP_QMSPI_IEN_XFR_DONE | MCHP_QMSPI_IEN_PROG_ERR in qmspi_xfr_start_async()
706 struct spi_qmspi_data *qdata = dev->data; in qmspi_xfr_async()
709 qdata->qstatus = 0; in qmspi_xfr_async()
710 qdata->xfr_len = 0; in qmspi_xfr_async()
718 /* Start (a)synchronous transaction using QMSPI Local-DMA */
727 struct spi_qmspi_data *qdata = dev->data; in qmspi_transceive()
728 struct spi_context *ctx = &qdata->ctx; in qmspi_transceive()
732 return -EINVAL; in qmspi_transceive()
739 spi_context_lock(&qdata->ctx, asynchronous, cb, user_data, config); in qmspi_transceive()
752 qdata->cb = cb; in qmspi_transceive()
753 qdata->userdata = user_data; in qmspi_transceive()
761 if (err) { /* de-assert CS# and give semaphore */ in qmspi_transceive()
771 if (!(config->operation & SPI_HOLD_ON_CS)) { in qmspi_transceive()
803 struct spi_qmspi_data *data = dev->data; in qmspi_release()
804 const struct spi_qmspi_config *cfg = dev->config; in qmspi_release()
805 struct qmspi_regs *regs = cfg->regs; in qmspi_release()
809 if (regs->STS & MCHP_QMSPI_STS_ACTIVE_RO) { in qmspi_release()
810 /* Force CS# to de-assert on next unit boundary */ in qmspi_release()
811 regs->EXE = MCHP_QMSPI_EXE_STOP; in qmspi_release()
812 while (regs->STS & MCHP_QMSPI_STS_ACTIVE_RO) { in qmspi_release()
820 spi_context_unlock_unconditionally(&data->ctx); in qmspi_release()
826 * All transfers use QMSPI Local-DMA specified by the Control register.
828 * Full-duplex always uses LDMA TX channel 0 and RX channel 0
829 * Half-duplex(dual/quad) use one of TX channel 0 or RX channel 0
833 const struct spi_qmspi_config *cfg = dev->config; in qmspi_xec_isr()
834 struct spi_qmspi_data *data = dev->data; in qmspi_xec_isr()
835 struct qmspi_regs *regs = cfg->regs; in qmspi_xec_isr()
836 uint32_t qstatus = regs->STS; in qmspi_xec_isr()
838 struct spi_context *ctx = &data->ctx; in qmspi_xec_isr()
842 regs->IEN = 0; in qmspi_xec_isr()
843 data->qstatus = qstatus; in qmspi_xec_isr()
844 regs->STS = MCHP_QMSPI_STS_RW1C_MASK; in qmspi_xec_isr()
845 mchp_xec_ecia_girq_src_clr(cfg->girq, cfg->girq_pos); in qmspi_xec_isr()
849 xstatus = -EIO; in qmspi_xec_isr()
850 data->qstatus |= BIT(7); in qmspi_xec_isr()
851 regs->EXE = MCHP_QMSPI_EXE_STOP; in qmspi_xec_isr()
854 if (data->cb) { in qmspi_xec_isr()
855 data->cb(dev, xstatus, data->userdata); in qmspi_xec_isr()
860 /* Clear Local-DMA enables in Mode and Control registers */ in qmspi_xec_isr()
861 regs->MODE &= ~(MCHP_QMSPI_M_LDMA_RX_EN | MCHP_QMSPI_M_LDMA_TX_EN); in qmspi_xec_isr()
862 regs->CTRL &= MCHP_QMSPI_C_IFM_MASK; in qmspi_xec_isr()
864 spi_context_update_tx(ctx, 1, data->xfr_len); in qmspi_xec_isr()
865 spi_context_update_rx(ctx, 1, data->xfr_len); in qmspi_xec_isr()
867 data->xfr_len = q_ldma_cfg(dev); in qmspi_xec_isr()
868 if (data->xfr_len) { in qmspi_xec_isr()
869 regs->STS = 0xffffffffu; in qmspi_xec_isr()
870 regs->EXE = MCHP_QMSPI_EXE_START; in qmspi_xec_isr()
871 regs->IEN = MCHP_QMSPI_IEN_XFR_DONE | MCHP_QMSPI_IEN_PROG_ERR in qmspi_xec_isr()
876 if (!(ctx->owner->operation & SPI_HOLD_ON_CS)) { in qmspi_xec_isr()
877 regs->EXE = MCHP_QMSPI_EXE_STOP; in qmspi_xec_isr()
878 spi_context_cs_control(&data->ctx, false); in qmspi_xec_isr()
881 spi_context_complete(&data->ctx, dev, xstatus); in qmspi_xec_isr()
883 if (data->cb) { in qmspi_xec_isr()
884 data->cb(dev, xstatus, data->userdata); in qmspi_xec_isr()
891 * define pinctr-1 values for each pin in the app/project DT overlay.
895 const struct spi_qmspi_config *devcfg = dev->config; in qmspi_xec_pm_action()
900 ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_DEFAULT); in qmspi_xec_pm_action()
903 ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_SLEEP); in qmspi_xec_pm_action()
904 if (ret == -ENOENT) { /* pinctrl-1 does not exist */ in qmspi_xec_pm_action()
909 ret = -ENOTSUP; in qmspi_xec_pm_action()
927 const struct spi_qmspi_config *cfg = dev->config; in qmspi_xec_init()
928 struct spi_qmspi_data *qdata = dev->data; in qmspi_xec_init()
929 struct qmspi_regs *regs = cfg->regs; in qmspi_xec_init()
933 qdata->base_freq_hz = 0u; in qmspi_xec_init()
934 qdata->qstatus = 0; in qmspi_xec_init()
935 qdata->np = cfg->width; in qmspi_xec_init()
937 qdata->xfr_len = 0; in qmspi_xec_init()
940 if (!cfg->clk_dev) { in qmspi_xec_init()
941 LOG_ERR("XEC QMSPI-LDMA clock device not configured"); in qmspi_xec_init()
942 return -EINVAL; in qmspi_xec_init()
945 ret = clock_control_on(cfg->clk_dev, (clock_control_subsys_t)&cfg->clksrc); in qmspi_xec_init()
947 LOG_ERR("XEC QMSPI-LDMA enable clock source error %d", ret); in qmspi_xec_init()
951 ret = clock_control_get_rate(cfg->clk_dev, clkss, &qdata->base_freq_hz); in qmspi_xec_init()
953 LOG_ERR("XEC QMSPI-LDMA clock get rate error %d", ret); in qmspi_xec_init()
959 mchp_xec_ecia_girq_src_clr(cfg->girq, cfg->girq_pos); in qmspi_xec_init()
961 ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); in qmspi_xec_init()
963 LOG_ERR("XEC QMSPI-LDMA pinctrl setup failed (%d)", ret); in qmspi_xec_init()
969 .frequency = cfg->clock_freq, in qmspi_xec_init()
975 LOG_ERR("XEC QMSPI-LDMA init configure failed (%d)", ret); in qmspi_xec_init()
980 cfg->irq_config_func(); in qmspi_xec_init()
981 mchp_xec_ecia_enable(cfg->girq, cfg->girq_pos); in qmspi_xec_init()
984 spi_context_unlock_unconditionally(&qdata->ctx); in qmspi_xec_init()