/***************************************************************************//** * @file * @brief QSPI Octal-SPI Flash Controller API ******************************************************************************* * # License * Copyright 2018 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * SPDX-License-Identifier: Zlib * * The licensor of this software is Silicon Laboratories Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ #ifndef EM_QSPI_H #define EM_QSPI_H #include "em_device.h" #if defined(QSPI_COUNT) && (QSPI_COUNT > 0) #ifdef __cplusplus extern "C" { #endif #include "em_bus.h" #include /***************************************************************************//** * @addtogroup qspi * @{ ******************************************************************************/ /******************************************************************************* ******************************* DEFINES *********************************** ******************************************************************************/ /******************************************************************************* ******************************** ENUMS ************************************ ******************************************************************************/ /** Transfer type. */ typedef enum { /** Single IO mode. DQ0 used for output and DQ1 as input. */ qspiTransferSingle = 0, /** Dual I/O transfer. DQ0 and DQ1 are used as both inputs and outputs. */ qspiTransferDual = 1, /** Quad I/O transfer. DQ0, DQ1, DQ2 and DQ3 are used as both inputs and outputs. */ qspiTransferQuad = 2, /** Octal I/O transfer. DQ[7:0] are used as both inputs and outputs. */ qspiTransferOctal = 3 } QSPI_TransferType_TypeDef; /******************************************************************************* ******************************* STRUCTS *********************************** ******************************************************************************/ /** QSPI Device Read Instruction Configuration Structure. */ typedef struct { /** Read opcode in non-xip mode. */ uint8_t opCode; /** Number of dummy read clock cycles. */ uint8_t dummyCycles; /** Transfer type used for address. */ QSPI_TransferType_TypeDef addrTransfer; /** Transfer type used for data. */ QSPI_TransferType_TypeDef dataTransfer; /** Transfer type used for instruction. */ QSPI_TransferType_TypeDef instTransfer; } QSPI_ReadConfig_TypeDef; /** Default Read Configuration Structure. */ #define QSPI_READCONFIG_DEFAULT \ { \ 0x03, /* 0x03 is the standard read opcode. */ \ 0, /* 0 dummy cycles. */ \ qspiTransferSingle, /* Single I/O mode. */ \ qspiTransferSingle, /* Single I/O mode. */ \ qspiTransferSingle, /* Single I/O mode. */ \ } /** QSPI Device Write Instruction Configuration Structure. */ typedef struct { /** Write opcode. */ uint8_t opCode; /** Number of dummy read clock cycles. */ uint8_t dummyCycles; /** Transfer type used for address. */ QSPI_TransferType_TypeDef addrTransfer; /** Transfer type used for data. */ QSPI_TransferType_TypeDef dataTransfer; /** * @brief * Enable/disable automatic issuing of WEL (Write Enable Latch) * command before a write operation. * * @details * When writing to a flash device, the WEL within the flash device must be * high before a write sequence can be issued. The QSPI peripheral can * automatically issue the WEL command before triggering a write sequence. * The command used for enabling the WEL is WREN (0x06) and is common between * devices. */ bool autoWEL; } QSPI_WriteConfig_TypeDef; /** Default Write Configuration Structure. */ #define QSPI_WRITECONFIG_DEFAULT \ { \ 0x02, /* 0x02 is the standard write opcode. */ \ 0, /* 0 dummy cycles. */ \ qspiTransferSingle, /* Single I/O mode. */ \ qspiTransferSingle, /* Single I/O mode. */ \ true, /* Send WEL command automatically. */ \ } /** QSPI Device Delay Configuration Structure. */ typedef struct { /** The minimal delay to keep the chip select line de-asserted between * two transactions. */ uint8_t deassert; /** Delay between one chip select being de-activated and the * activation of another. */ uint8_t deviceSwitch; /** Delay between last bit and chip select de-assert. */ uint8_t lastBit; /** Delay chip select assert and first bit in a transaction. */ uint8_t firstBit; } QSPI_DelayConfig_TypeDef; /** Defines command to be executed using STIG mechanism. */ typedef struct { /** Command op-code. */ uint8_t cmdOpcode; /** Number of Read Data Bytes. */ uint16_t readDataSize; /** Number of Address Bytes. */ uint8_t addrSize; /** Number of Write Data Bytes. */ uint8_t writeDataSize; /** Number of dummy cycles. */ uint8_t dummyCycles; /** Mode Bit Configuration register are sent following the address bytes. */ bool modeBitEnable; /** Flash command address. */ uint32_t address; /** Buffer for read data. */ void * readBuffer; /** Buffer with data to write. */ void * writeBuffer; } QSPI_StigCmd_TypeDef; /** QSPI initialization structure. */ typedef struct { /** Enable/disable Quad SPI when initialization is completed. */ bool enable; /** * Master mode baud rate divisor. Values can be even numbers in the range * [2-32] inclusive. */ uint8_t divisor; } QSPI_Init_TypeDef; /** Default configuration for QSPI_Init_TypeDef structure. */ #define QSPI_INIT_DEFAULT \ { \ true, /* Enable Quad SPI. */ \ 32, /* Divide QSPI clock by 32. */ \ } /******************************************************************************* ****************************** PROTOTYPES ********************************* ******************************************************************************/ void QSPI_Init(QSPI_TypeDef * qspi, const QSPI_Init_TypeDef * init); void QSPI_ReadConfig(QSPI_TypeDef * qspi, const QSPI_ReadConfig_TypeDef * config); void QSPI_WriteConfig(QSPI_TypeDef * qspi, const QSPI_WriteConfig_TypeDef * config); void QSPI_ExecStigCmd(QSPI_TypeDef * qspi, const QSPI_StigCmd_TypeDef * stigCmd); /***************************************************************************//** * @brief * Wait for the QSPI to go into idle state. * * @param[in] qspi * Pointer to QSPI peripheral register block. ******************************************************************************/ __STATIC_INLINE void QSPI_WaitForIdle(QSPI_TypeDef * qspi) { while ((qspi->CONFIG & _QSPI_CONFIG_IDLE_MASK) == 0) ; } /***************************************************************************//** * @brief * Get the fill level of the write partition of the QSPI internal SRAM. * * @param[in] qspi * Pointer to QSPI peripheral register block. * * @return * SRAM fill level of the write partition. The value is the number of 4 byte * words in the write partition. ******************************************************************************/ __STATIC_INLINE uint16_t QSPI_GetWriteLevel(QSPI_TypeDef * qspi) { return (qspi->SRAMFILL & _QSPI_SRAMFILL_SRAMFILLINDACWRITE_MASK) >> _QSPI_SRAMFILL_SRAMFILLINDACWRITE_SHIFT; } /***************************************************************************//** * @brief * Get the fill level of the read partition of the QSPI internal SRAM. * * @param[in] qspi * Pointer to QSPI peripheral register block. * * @return * SRAM fill level of the read partition. The value is the number of 4 byte * words in the read partition. ******************************************************************************/ __STATIC_INLINE uint16_t QSPI_GetReadLevel(QSPI_TypeDef * qspi) { return (qspi->SRAMFILL & _QSPI_SRAMFILL_SRAMFILLINDACREAD_MASK) >> _QSPI_SRAMFILL_SRAMFILLINDACREAD_SHIFT; } /***************************************************************************//** * @brief * Enable/disable Quad SPI. * * @param[in] qspi * Pointer to QSPI peripheral register block. * * @param[in] enable * true to enable Quad SPI, false to disable Quad SPI. ******************************************************************************/ __STATIC_INLINE void QSPI_Enable(QSPI_TypeDef * qspi, bool enable) { BUS_RegBitWrite(&qspi->CONFIG, _QSPI_CONFIG_ENBSPI_SHIFT, enable ? 1 : 0); } /***************************************************************************//** * @brief * Get the current interrupt flags. * * @param[in] qspi * Pointer to QSPI peripheral register block. * * @return * This functions returns the current interrupt flags that are set. ******************************************************************************/ __STATIC_INLINE uint32_t QSPI_IntGet(QSPI_TypeDef * qspi) { return qspi->IRQSTATUS; } /***************************************************************************//** * @brief * Clear interrupt flags. * * @param[in] qspi * Pointer to QSPI peripheral register block. * * @param[in] flags * The interrupt flags to clear. ******************************************************************************/ __STATIC_INLINE void QSPI_IntClear(QSPI_TypeDef * qspi, uint32_t flags) { qspi->IRQSTATUS = flags; } /***************************************************************************//** * @brief * Enable interrupts. * * @param[in] qspi * Pointer to QSPI peripheral register block. * * @param[in] flags * The interrupt flags to enable. ******************************************************************************/ __STATIC_INLINE void QSPI_IntEnable(QSPI_TypeDef * qspi, uint32_t flags) { qspi->IRQMASK = flags & (~_QSPI_IRQMASK_MASK); } /***************************************************************************//** * @brief * Disable interrupts. * * @param[in] qspi * Pointer to QSPI peripheral register block. * * @param[in] flags * The interrupt flags to disable. ******************************************************************************/ __STATIC_INLINE void QSPI_IntDisable(QSPI_TypeDef * qspi, uint32_t flags) { qspi->IRQMASK = ~flags & (~_QSPI_IRQMASK_MASK); } /** @} (end addtogroup qspi) */ #ifdef __cplusplus } #endif #endif /* defined(QSPI_COUNT) && (QSPI_COUNT > 0) */ #endif /* EM_QSPI_H */