diff options
Diffstat (limited to 'chip/mchp/qmspi.c')
-rw-r--r-- | chip/mchp/qmspi.c | 700 |
1 files changed, 0 insertions, 700 deletions
diff --git a/chip/mchp/qmspi.c b/chip/mchp/qmspi.c deleted file mode 100644 index 72eaa91d37..0000000000 --- a/chip/mchp/qmspi.c +++ /dev/null @@ -1,700 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* QMSPI master module for MCHP MEC family */ - -#include "common.h" -#include "console.h" -#include "dma.h" -#include "gpio.h" -#include "registers.h" -#include "spi.h" -#include "timer.h" -#include "util.h" -#include "hooks.h" -#include "task.h" -#include "dma_chip.h" -#include "spi_chip.h" -#include "qmspi_chip.h" -#include "tfdp_chip.h" - -#define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) - -#define QMSPI_TRANSFER_TIMEOUT (100 * MSEC) -#define QMSPI_BYTE_TRANSFER_TIMEOUT_US (3 * MSEC) -#define QMSPI_BYTE_TRANSFER_POLL_INTERVAL_US 20 - - - -#ifndef CONFIG_MCHP_QMSPI_TX_DMA -#ifdef LFW -/* - * MCHP 32-bit timer 0 configured for 1us count down mode and no - * interrupt in the LFW environment. Don't need to sleep CPU in LFW. - */ -static int qmspi_wait(uint32_t mask, uint32_t mval) -{ - uint32_t t1, t2, td; - - t1 = MCHP_TMR32_CNT(0); - - while ((MCHP_QMSPI0_STS & mask) != mval) { - t2 = MCHP_TMR32_CNT(0); - if (t1 >= t2) - td = t1 - t2; - else - td = t1 + (0xfffffffful - t2); - if (td > QMSPI_BYTE_TRANSFER_TIMEOUT_US) - return EC_ERROR_TIMEOUT; - } - return EC_SUCCESS; -} -#else -/* - * This version uses the full EC_RO/RW timer infrastructure and it needs - * a timer ISR to handle timer underflow. Without the ISR we observe false - * timeouts when debugging with JTAG. - * QMSPI_BYTE_TRANSFER_TIMEOUT_US currently 3ms - * QMSPI_BYTE_TRANSFER_POLL_INTERVAL_US currently 100 us - */ - -static int qmspi_wait(uint32_t mask, uint32_t mval) -{ - timestamp_t deadline; - - deadline.val = get_time().val + (QMSPI_BYTE_TRANSFER_TIMEOUT_US); - - while ((MCHP_QMSPI0_STS & mask) != mval) { - if (timestamp_expired(deadline, NULL)) - return EC_ERROR_TIMEOUT; - - usleep(QMSPI_BYTE_TRANSFER_POLL_INTERVAL_US); - } - return EC_SUCCESS; -} -#endif /* #ifdef LFW */ -#endif /* #ifndef CONFIG_MCHP_QMSPI_TX_DMA */ - -/* - * Wait for QMSPI read using DMA to finish. - * DMA subsystem has 100 ms timeout - */ -int qmspi_transaction_wait(const struct spi_device_t *spi_device) -{ - const struct dma_option *opdma; - - opdma = spi_dma_option(spi_device, SPI_DMA_OPTION_RD); - if (opdma != NULL) - return dma_wait(opdma->channel); - - return EC_ERROR_INVAL; -} - -/* - * Create QMSPI transmit data descriptor not using DMA. - * Transmit on MOSI pin (single/full-duplex) from TX FIFO. - * TX FIFO filled by CPU. - * Caller will apply close and last flags if applicable. - */ -#ifndef CONFIG_MCHP_QMSPI_TX_DMA -static uint32_t qmspi_build_tx_descr(uint32_t ntx, uint32_t ndid) -{ - uint32_t d; - - d = MCHP_QMSPI_C_1X + MCHP_QMSPI_C_TX_DATA; - d |= ((ndid & 0x0F) << MCHP_QMSPI_C_NEXT_DESCR_BITPOS); - - if (ntx <= MCHP_QMSPI_C_MAX_UNITS) - d |= MCHP_QMSPI_C_XFRU_1B; - else { - if ((ntx & 0x0f) == 0) { - ntx >>= 4; - d |= MCHP_QMSPI_C_XFRU_16B; - } else if ((ntx & 0x03) == 0) { - ntx >>= 2; - d |= MCHP_QMSPI_C_XFRU_4B; - } else - d |= MCHP_QMSPI_C_XFRU_1B; - - if (ntx > MCHP_QMSPI_C_MAX_UNITS) - return 0; /* overflow unit count field */ - } - - d |= (ntx << MCHP_QMSPI_C_NUM_UNITS_BITPOS); - - return d; -} - -/* - * Create QMSPI receive data descriptor using DMA. - * Receive data on MISO pin (single/full-duplex) and store in QMSPI - * RX FIFO. QMSPI triggers DMA channel to read from RX FIFO and write - * to memory. Return value is an uint64_t where low 32-bit word is the - * descriptor and upper 32-bit word is DMA channel unit length with - * value (1, 2, or 4). - * Caller will apply close and last flags if applicable. - */ -static uint64_t qmspi_build_rx_descr(uint32_t raddr, - uint32_t nrx, uint32_t ndid) -{ - uint32_t d, dmau, na; - uint64_t u; - - d = MCHP_QMSPI_C_1X + MCHP_QMSPI_C_RX_EN; - d |= ((ndid & 0x0F) << MCHP_QMSPI_C_NEXT_DESCR_BITPOS); - - dmau = 1; - na = (raddr | nrx) & 0x03; - if (na == 0) { - d |= MCHP_QMSPI_C_RX_DMA_4B; - dmau <<= 2; - } else if (na == 0x02) { - d |= MCHP_QMSPI_C_RX_DMA_2B; - dmau <<= 1; - } else { - d |= MCHP_QMSPI_C_RX_DMA_1B; - } - - if ((nrx & 0x0f) == 0) { - nrx >>= 4; - d |= MCHP_QMSPI_C_XFRU_16B; - } else if ((nrx & 0x03) == 0) { - nrx >>= 2; - d |= MCHP_QMSPI_C_XFRU_4B; - } else { - d |= MCHP_QMSPI_C_XFRU_1B; - } - - u = 0; - if (nrx <= MCHP_QMSPI_C_MAX_UNITS) { - d |= (nrx << MCHP_QMSPI_C_NUM_UNITS_BITPOS); - u = dmau; - u <<= 32; - u |= d; - } - - return u; -} -#endif - -#ifdef CONFIG_MCHP_QMSPI_TX_DMA - -#define QMSPI_ERR_ANY 0x80 -#define QMSPI_ERR_BAD_PTR 0x81 -#define QMSPI_ERR_OUT_OF_DESCR 0x85 - -/* - * bits[1:0] of word - * 1 -> 0 - * 2 -> 1 - * 4 -> 2 - */ -static uint32_t qmspi_pins_encoding(uint8_t npins) -{ - return (uint32_t)(npins >> 1) & 0x03; -} - -/* - * Clear status, FIFO's, and all descriptors. - * Enable descriptor mode. - */ -static void qmspi_descr_mode_ready(void) -{ - int i; - - MCHP_QMSPI0_CTRL = 0; - MCHP_QMSPI0_IEN = 0; - MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_CLR_FIFOS; - MCHP_QMSPI0_STS = 0xfffffffful; - MCHP_QMSPI0_CTRL = MCHP_QMSPI_C_DESCR_MODE_EN; - /* clear all descriptors */ - for (i = 0; i < MCHP_QMSPI_MAX_DESCR; i++) - MCHP_QMSPI0_DESCR(i) = 0; -} - -/* - * helper - * did = zero based index of start descriptor - * descr = descriptor configuration - * nb = number of bytes to transfer - * Return index of last descriptor allocated or 0xffff - * if out of descriptors. - * Algorithm: - * If requested number of bytes will fit in one descriptor then - * configure descriptor for QMSPI byte units and return. - * Otherwise allocate multiple descriptor using QMSPI 16-byte mode - * and remaining < 16 bytes in byte unit descriptor until all bytes - * exhausted or out of descriptors error. - */ -static uint32_t qmspi_descr_alloc(uint32_t did, - uint32_t descr, uint32_t nb) -{ - uint32_t nu; - - while (nb) { - if (did >= MCHP_QMSPI_MAX_DESCR) - return 0xffff; - - descr &= ~(MCHP_QMSPI_C_NUM_UNITS_MASK + - MCHP_QMSPI_C_XFRU_MASK); - - if (nb < (MCHP_QMSPI_C_MAX_UNITS + 1)) { - descr |= MCHP_QMSPI_C_XFRU_1B; - descr += (nb << MCHP_QMSPI_C_NUM_UNITS_BITPOS); - nb = 0; - } else { - descr |= MCHP_QMSPI_C_XFRU_16B; - nu = (nb >> 4) & MCHP_QMSPI_C_NUM_UNITS_MASK0; - descr += (nu << MCHP_QMSPI_C_NUM_UNITS_BITPOS); - nb -= (nu << 4); - } - - descr |= ((did+1) << MCHP_QMSPI_C_NEXT_DESCR_BITPOS); - MCHP_QMSPI0_DESCR(did) = descr; - if (nb) - did++; - } - - return did; -} - -/* - * Build one or more descriptors for command/data transmit. - * cfg b[7:0] = start descriptor index - * cfg b[15:8] = number of pins for transmit. - * If bytes to transmit will fit in TX FIFO then fill TX FIFO and build - * one descriptor. - * Otherwise build one or more descriptors to fill TX FIFO using DMA - * channel and configure the DMA channel for memory to device transfer. - */ -static uint32_t qmspi_xmit_data_descr(const struct dma_option *opdma, - uint32_t cfg, - const uint8_t *data, - uint32_t ndata) -{ - uint32_t d, d2, did, dma_cfg; - - did = cfg & 0x0f; - d = qmspi_pins_encoding((cfg >> 8) & 0x07); - - if (ndata <= MCHP_QMSPI_TX_FIFO_LEN) { - d2 = d + (ndata << MCHP_QMSPI_C_NUM_UNITS_BITPOS) + - MCHP_QMSPI_C_XFRU_1B + MCHP_QMSPI_C_TX_DATA; - d2 += ((did + 1) << MCHP_QMSPI_C_NEXT_DESCR_BITPOS); - MCHP_QMSPI0_DESCR(did) = d2; - while (ndata--) - MCHP_QMSPI0_TX_FIFO8 = *data++; - } else { // TX DMA - if (((uint32_t)data | ndata) & 0x03) { - dma_cfg = 1; - d |= (MCHP_QMSPI_C_TX_DATA + - MCHP_QMSPI_C_TX_DMA_1B); - } else { - dma_cfg = 4; - d |= (MCHP_QMSPI_C_TX_DATA + - MCHP_QMSPI_C_TX_DMA_4B); - } - did = qmspi_descr_alloc(did, d, ndata); - if (did == 0xffff) - return QMSPI_ERR_OUT_OF_DESCR; - - dma_clr_chan(opdma->channel); - dma_cfg_buffers(opdma->channel, data, ndata, - (void *)MCHP_QMSPI0_TX_FIFO_ADDR); - dma_cfg_xfr(opdma->channel, dma_cfg, - MCHP_DMA_QMSPI0_TX_REQ_ID, - (DMA_FLAG_M2D + DMA_FLAG_INCR_MEM)); - dma_run(opdma->channel); - } - - return did; -} - -/* - * QMSPI0 Start - * flags - * b[0] = 1 de-assert chip select when done - * b[1] = 1 enable QMSPI interrupts - * b[2] = 1 start - */ -void qmspi_cfg_irq_start(uint8_t flags) -{ - MCHP_INT_DISABLE(MCHP_QMSPI_GIRQ) = MCHP_QMSPI_GIRQ_BIT; - MCHP_INT_SOURCE(MCHP_QMSPI_GIRQ) = MCHP_QMSPI_GIRQ_BIT; - MCHP_QMSPI0_IEN = 0; - - if (flags & (1u << 1)) { - MCHP_QMSPI0_IEN = (MCHP_QMSPI_STS_DONE + - MCHP_QMSPI_STS_PROG_ERR); - MCHP_INT_ENABLE(MCHP_QMSPI_GIRQ) = MCHP_QMSPI_GIRQ_BIT; - } - - if (flags & (1u << 2)) - MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_START; -} - -/* - * QMSPI transmit and/or receive - * np_flags - * b[7:0] = flags - * b[0] = close(de-assert chip select when done) - * b[1] = enable Done and ProgError interrupt - * b[2] = start - * b[15:8] = number of tx pins - * b[24:16] = number of rx pins - * - * returns last descriptor 0 <= index < MCHP_QMSPI_MAX_DESCR - * or error (bit[7]==1) - */ -uint8_t qmspi_xfr(const struct spi_device_t *spi_device, - uint32_t np_flags, - const uint8_t *txdata, uint32_t ntx, - uint8_t *rxdata, uint32_t nrx) -{ - uint32_t d, did, dma_cfg; - const struct dma_option *opdma; - - qmspi_descr_mode_ready(); - - did = 0; - if (ntx) { - if (txdata == NULL) - return QMSPI_ERR_BAD_PTR; - - opdma = spi_dma_option(spi_device, SPI_DMA_OPTION_WR); - - d = qmspi_pins_encoding((np_flags >> 8) & 0xff); - dma_cfg = (np_flags & 0xFF00) + did; - did = qmspi_xmit_data_descr(opdma, dma_cfg, txdata, ntx); - if (did & QMSPI_ERR_ANY) - return (uint8_t)(did & 0xff); - - if (nrx) - did++; /* point to next descriptor */ - } - - if (nrx) { - if (rxdata == NULL) - return QMSPI_ERR_BAD_PTR; - - if (did >= MCHP_QMSPI_MAX_DESCR) - return QMSPI_ERR_OUT_OF_DESCR; - - d = qmspi_pins_encoding((np_flags >> 16) & 0xff); - /* compute DMA units: 1 or 4 */ - if (((uint32_t)rxdata | nrx) & 0x03) { - dma_cfg = 1; - d |= (MCHP_QMSPI_C_RX_EN + MCHP_QMSPI_C_RX_DMA_1B); - } else { - dma_cfg = 4; - d |= (MCHP_QMSPI_C_RX_EN + MCHP_QMSPI_C_RX_DMA_4B); - } - did = qmspi_descr_alloc(did, d, nrx); - if (did & QMSPI_ERR_ANY) - return (uint8_t)(did & 0xff); - - opdma = spi_dma_option(spi_device, SPI_DMA_OPTION_RD); - dma_clr_chan(opdma->channel); - dma_cfg_buffers(opdma->channel, rxdata, nrx, - (void *)MCHP_QMSPI0_RX_FIFO_ADDR); - dma_cfg_xfr(opdma->channel, dma_cfg, - MCHP_DMA_QMSPI0_RX_REQ_ID, - (DMA_FLAG_D2M + DMA_FLAG_INCR_MEM)); - dma_run(opdma->channel); - } - - if (ntx || nrx) { - d = MCHP_QMSPI0_DESCR(did); - d |= MCHP_QMSPI_C_DESCR_LAST; - if (np_flags & 0x01) - d |= MCHP_QMSPI_C_CLOSE; - MCHP_QMSPI0_DESCR(did) = d; - qmspi_cfg_irq_start(np_flags & 0xFF); - } - - return (uint8_t)(did & 0xFF); -} -#endif /* #ifdef CONFIG_MCHP_QMSPI_TX_DMA */ - -/* - * QMSPI controller must control chip select therefore this routine - * configures QMSPI to assert SPI CS# and de-assert when done. - * Transmit using QMSPI TX FIFO only when tx data fits in TX FIFO else - * use TX DMA. - * Transmit and receive will allocate as many QMSPI descriptors as - * needed for data size. This could result in an error if the maximum - * number of descriptors is exceeded. - * Descriptors are limited to 0x7FFF units where unit size is 1, 4, or - * 16 bytes. Code determines unit size based upon number of bytes and - * alignment of data buffer. - * DMA channel will move data in units of 1 or 4 bytes also based upon - * the number of data bytes and buffer alignment. - * The most efficient transfers are those where TX and RX buffers are - * aligned >= 4 bytes and the number of bytes is a multiple of 4. - * NOTE on SPI flash commands: - * This routine does NOT handle SPI flash commands requiring - * extra clocks or special mode bytes. Extra clocks and special mode - * bytes require additional descriptors. For example the flash read - * dual command (0x3B): - * 1. First descriptor transmits 4 bytes (opcode + 24-bit address) on - * one pin (IO0). - * 2. Second descriptor set for 2 IO pins, 2 bytes, TX disabled. When - * this descriptor is executed QMSPI will tri-state IO0 & IO1 and - * output 8 clocks (dual mode 4 clocks per byte). The SPI flash may - * turn on its output drivers on the first clock. - * 3. Third descriptor set for 2 IO pins, read data using DMA. Unit - * size and DMA unit size based on number of bytes to read and - * alignment of destination buffer. - * The common SPI API will be required to supply more information about - * SPI flash read commands. A further complication is some larger SPI - * flash devices support a 4-byte address mode. 4-byte address mode can - * be implemented as separate command code or a configuration bit in - * the SPI flash that changes the default 24-bit address command to - * require a 32-bit address. - * 0x03 is 1-1-1 - * 0x3B is 1-1-2 with 8 clocks - * 0x6B is 1-1-4 with 8 clocks - * 0xBB is 1-2-2 with 4 clocks - * Number of IO pins for command - * Number of IO pins for address - * Number of IO pins for data - * Number of bit/bytes for address (3 or 4) - * Number of clocks after address phase - */ -#ifdef CONFIG_MCHP_QMSPI_TX_DMA -int qmspi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - uint32_t np_flags, ntx, nrx; - int ret; - uint8_t rc; - - ntx = 0; - if (txlen >= 0) - ntx = (uint32_t)txlen; - - nrx = 0; - if (rxlen >= 0) - nrx = (uint32_t)rxlen; - - np_flags = 0x010105; /* b[0]=1 close on done, b[2]=1 start */ - rc = qmspi_xfr(spi_device, np_flags, - txdata, ntx, - rxdata, nrx); - - if (rc & QMSPI_ERR_ANY) - return EC_ERROR_INVAL; - - ret = EC_SUCCESS; - return ret; -} -#else -/* - * Transmit using CPU and QMSPI TX FIFO(no DMA). - * Receive using DMA as above. - */ -int qmspi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - const struct dma_option *opdma; - uint32_t d, did, dmau; - uint64_t u; - - if (spi_device == NULL) - return EC_ERROR_PARAM1; - - /* soft reset the controller */ - MCHP_QMSPI0_MODE_ACT_SRST = MCHP_QMSPI_M_SOFT_RESET; - d = spi_device->div; - d <<= MCHP_QMSPI_M_CLKDIV_BITPOS; - d += (MCHP_QMSPI_M_ACTIVATE + MCHP_QMSPI_M_SPI_MODE0); - MCHP_QMSPI0_MODE = d; - MCHP_QMSPI0_CTRL = MCHP_QMSPI_C_DESCR_MODE_EN; - - d = did = 0; - - if (txlen > 0) { - if (txdata == NULL) - return EC_ERROR_PARAM2; - - d = qmspi_build_tx_descr((uint32_t)txlen, 1); - if (d == 0) /* txlen too large */ - return EC_ERROR_OVERFLOW; - - MCHP_QMSPI0_DESCR(did) = d; - } - - if (rxlen > 0) { - if (rxdata == NULL) - return EC_ERROR_PARAM4; - - u = qmspi_build_rx_descr((uint32_t)rxdata, - (uint32_t)rxlen, 2); - - d = (uint32_t)u; - dmau = u >> 32; - - if (txlen > 0) - did++; - MCHP_QMSPI0_DESCR(did) = d; - - opdma = spi_dma_option(spi_device, SPI_DMA_OPTION_RD); - dma_xfr_start_rx(opdma, dmau, (uint32_t)rxlen, rxdata); - } - - MCHP_QMSPI0_DESCR(did) |= (MCHP_QMSPI_C_CLOSE + - MCHP_QMSPI_C_DESCR_LAST); - - MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_START; - - while (txlen--) { - if (MCHP_QMSPI0_STS & MCHP_QMSPI_STS_TX_BUFF_FULL) { - if (qmspi_wait(MCHP_QMSPI_STS_TX_BUFF_EMPTY, - MCHP_QMSPI_STS_TX_BUFF_EMPTY) != - EC_SUCCESS) { - MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_STOP; - return EC_ERROR_TIMEOUT; - } - } else - MCHP_QMSPI0_TX_FIFO8 = *txdata++; - } - - return EC_SUCCESS; -} -#endif /* #ifdef CONFIG_MCHP_QMSPI_TX_DMA */ - -/* - * Wait for QMSPI descriptor mode transfer to finish. - * QMSPI is configured to perform a complete transaction. - * Assert CS# - * optional transmit - * CPU keeps filling TX FIFO until all bytes are transmitted. - * optional receive - * QMSPI is configured to read rxlen bytes and uses a DMA channel - * to move data from its RX FIFO to memory. - * De-assert CS# - * This routine can be called with QMSPI hardware in four states: - * 1. Transmit only and QMSPI has finished (empty TX FIFO) by the time - * this routine is called. QMSPI.Status transfer done status will be - * set and QMSPI HW has de-asserted SPI CS#. - * 2. Transmit only and QMSPI TX FIFO is still transmitting. - * QMSPI transfer done status is not asserted and CS# is still - * asserted. QMSPI HW will de-assert CS# when done or firmware - * manually stops QMSPI. - * 3. Receive was enabled and DMA channel is moving data from - * QMSPI RX FIFO to memory. QMSPI.Status transfer done and DMA done - * status bits are not set. QMSPI SPI CS# will stay asserted until - * transaction finishes or firmware manually stops QMSPI. - * 4. Receive was enabled and DMA channel is finished. QMSPI RX FIFO - * should be empty and DMA channel is done. QMSPI.Status transfer - * done and DMA done status bits will be set. QMSPI HW has de-asserted - * SPI CS#. - * We are using QMSPI in descriptor mode. The definition of QMSPI.Status - * transfer complete bit in this mode is: complete will be set to 1 only - * when the last buffer completes its transfer. - * TX only sets complete when transfer unit count is matched and all units - * have been clocked out of the TX FIFO. - * RX DMA transfer complete will be set when the last transfer unit - * is out of the RX FIFO but DMA may not be complete until it finishes - * moving the transfer unit to memory. - * If TX only spin on QMSPI.Status Transfer_Complete bit. - * If RX used spin on QMsPI.Status Transfer_Complete and DMA_Complete. - * Search descriptors looking for RX DMA enabled. - * If RX DMA is enabled add DMA complete flag to status mask. - * Spin while QMSPI.Status & mask != mask or timeout. - * If timeout force QMSPI to stop and exit spin loop. - * if DMA was enabled disable DMA channel. - * Clear QMSPI.Status and FIFO's - */ -int qmspi_transaction_flush(const struct spi_device_t *spi_device) -{ - int ret; - uint32_t qsts, mask; - const struct dma_option *opdma; - timestamp_t deadline; - - if (spi_device == NULL) - return EC_ERROR_PARAM1; - - mask = MCHP_QMSPI_STS_DONE; - - ret = EC_SUCCESS; - deadline.val = get_time().val + QMSPI_TRANSFER_TIMEOUT; - - qsts = MCHP_QMSPI0_STS; - while ((qsts & mask) != mask) { - if (timestamp_expired(deadline, NULL)) { - MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_STOP; - ret = EC_ERROR_TIMEOUT; - break; - } - usleep(QMSPI_BYTE_TRANSFER_POLL_INTERVAL_US); - qsts = MCHP_QMSPI0_STS; - } - - /* clear transmit DMA channel */ - opdma = spi_dma_option(spi_device, SPI_DMA_OPTION_WR); - if (opdma == NULL) - return EC_ERROR_INVAL; - - dma_disable(opdma->channel); - dma_clear_isr(opdma->channel); - - /* clear receive DMA channel */ - opdma = spi_dma_option(spi_device, SPI_DMA_OPTION_RD); - if (opdma == NULL) - return EC_ERROR_INVAL; - - dma_disable(opdma->channel); - dma_clear_isr(opdma->channel); - - /* clear QMSPI FIFO's */ - MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_CLR_FIFOS; - MCHP_QMSPI0_STS = 0xffffffff; - - return ret; -} - -/** - * Enable QMSPI controller and MODULE_SPI_FLASH pins. - * - * @param hw_port b[3:0]=0 and b[7:4]=0 - * @param enable - * @return EC_SUCCESS or EC_ERROR_INVAL if port is unrecognized - * @note called by spi_enable in mec1701/spi.c - * - */ -int qmspi_enable(int hw_port, int enable) -{ - uint8_t unused __attribute__((unused)) = 0; - - trace2(0, QMSPI, 0, "qmspi_enable: port = %d enable = %d", - hw_port, enable); - - if (hw_port != QMSPI0_PORT) - return EC_ERROR_INVAL; - - gpio_config_module(MODULE_SPI_FLASH, (enable > 0)); - - if (enable) { - MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_QMSPI); - MCHP_QMSPI0_MODE_ACT_SRST = MCHP_QMSPI_M_SOFT_RESET; - unused = MCHP_QMSPI0_MODE_ACT_SRST; - MCHP_QMSPI0_MODE = (MCHP_QMSPI_M_ACTIVATE + - MCHP_QMSPI_M_SPI_MODE0 + - MCHP_QMSPI_M_CLKDIV_12M); - } else { - MCHP_QMSPI0_MODE_ACT_SRST = MCHP_QMSPI_M_SOFT_RESET; - unused = MCHP_QMSPI0_MODE_ACT_SRST; - MCHP_QMSPI0_MODE_ACT_SRST = 0; - MCHP_PCR_SLP_EN_DEV(MCHP_PCR_QMSPI); - } - - return EC_SUCCESS; -} - |