1 /***************************************************************************//**
2  * @file
3  * @brief QSPI Octal-SPI Flash Controller API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #ifndef EM_QSPI_H
32 #define EM_QSPI_H
33 
34 #include "em_device.h"
35 #if defined(QSPI_COUNT) && (QSPI_COUNT > 0)
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 #include "em_bus.h"
42 #include <stdbool.h>
43 
44 /***************************************************************************//**
45  * @addtogroup qspi
46  * @{
47  ******************************************************************************/
48 
49 /*******************************************************************************
50  *******************************   DEFINES   ***********************************
51  ******************************************************************************/
52 
53 /*******************************************************************************
54  ********************************   ENUMS   ************************************
55  ******************************************************************************/
56 
57 /** Transfer type. */
58 typedef enum {
59   /** Single IO mode. DQ0 used for output and DQ1 as input. */
60   qspiTransferSingle = 0,
61 
62   /** Dual I/O transfer. DQ0 and DQ1 are used as both inputs and outputs. */
63   qspiTransferDual   = 1,
64 
65   /** Quad I/O transfer. DQ0, DQ1, DQ2 and DQ3 are used as both inputs and outputs. */
66   qspiTransferQuad   = 2,
67 
68   /** Octal I/O transfer. DQ[7:0] are used as both inputs and outputs. */
69   qspiTransferOctal  = 3
70 } QSPI_TransferType_TypeDef;
71 
72 /*******************************************************************************
73  *******************************   STRUCTS   ***********************************
74  ******************************************************************************/
75 
76 /** QSPI Device Read Instruction Configuration Structure. */
77 typedef struct {
78   /** Read opcode in non-xip mode. */
79   uint8_t                   opCode;
80 
81   /** Number of dummy read clock cycles. */
82   uint8_t                   dummyCycles;
83 
84   /** Transfer type used for address. */
85   QSPI_TransferType_TypeDef addrTransfer;
86 
87   /** Transfer type used for data. */
88   QSPI_TransferType_TypeDef dataTransfer;
89 
90   /** Transfer type used for instruction. */
91   QSPI_TransferType_TypeDef instTransfer;
92 } QSPI_ReadConfig_TypeDef;
93 
94 /** Default Read Configuration Structure. */
95 #define QSPI_READCONFIG_DEFAULT                                  \
96   {                                                              \
97     0x03,                /* 0x03 is the standard read opcode. */ \
98     0,                   /* 0 dummy cycles. */                   \
99     qspiTransferSingle,  /* Single I/O mode. */                  \
100     qspiTransferSingle,  /* Single I/O mode. */                  \
101     qspiTransferSingle,  /* Single I/O mode. */                  \
102   }
103 
104 /** QSPI Device Write Instruction Configuration Structure. */
105 typedef struct {
106   /** Write opcode. */
107   uint8_t                   opCode;
108 
109   /** Number of dummy read clock cycles. */
110   uint8_t                   dummyCycles;
111 
112   /** Transfer type used for address. */
113   QSPI_TransferType_TypeDef addrTransfer;
114 
115   /** Transfer type used for data. */
116   QSPI_TransferType_TypeDef dataTransfer;
117 
118   /**
119    * @brief
120    *   Enable/disable automatic issuing of WEL (Write Enable Latch)
121    *   command before a write operation.
122    *
123    * @details
124    *   When writing to a flash device, the WEL within the flash device must be
125    *   high before a write sequence can be issued. The QSPI peripheral can
126    *   automatically issue the WEL command before triggering a write sequence.
127    *   The command used for enabling the WEL is WREN (0x06) and is common between
128    *   devices. */
129   bool                      autoWEL;
130 } QSPI_WriteConfig_TypeDef;
131 
132 /** Default Write Configuration Structure. */
133 #define QSPI_WRITECONFIG_DEFAULT                                  \
134   {                                                               \
135     0x02,                /* 0x02 is the standard write opcode. */ \
136     0,                   /* 0 dummy cycles. */                    \
137     qspiTransferSingle,  /* Single I/O mode. */                   \
138     qspiTransferSingle,  /* Single I/O mode. */                   \
139     true,                /* Send WEL command automatically. */    \
140   }
141 
142 /** QSPI Device Delay Configuration Structure. */
143 typedef struct {
144   /** The minimal delay to keep the chip select line de-asserted between
145    *  two transactions. */
146   uint8_t deassert;
147 
148   /** Delay between one chip select being de-activated and the
149    * activation of another. */
150   uint8_t deviceSwitch;
151 
152   /** Delay between last bit and chip select de-assert. */
153   uint8_t lastBit;
154 
155   /** Delay chip select assert and first bit in a transaction. */
156   uint8_t firstBit;
157 } QSPI_DelayConfig_TypeDef;
158 
159 /** Defines command to be executed using STIG mechanism. */
160 typedef struct {
161   /** Command op-code. */
162   uint8_t  cmdOpcode;
163   /** Number of Read Data Bytes. */
164   uint16_t readDataSize;
165   /** Number of Address Bytes. */
166   uint8_t  addrSize;
167   /** Number of Write Data Bytes. */
168   uint8_t  writeDataSize;
169   /** Number of dummy cycles. */
170   uint8_t  dummyCycles;
171   /** Mode Bit Configuration register are sent following the address bytes. */
172   bool     modeBitEnable;
173   /** Flash command address. */
174   uint32_t address;
175   /** Buffer for read data. */
176   void *   readBuffer;
177   /** Buffer with data to write. */
178   void *   writeBuffer;
179 } QSPI_StigCmd_TypeDef;
180 
181 /** QSPI initialization structure. */
182 typedef struct {
183   /** Enable/disable Quad SPI when initialization is completed. */
184   bool                       enable;
185 
186   /**
187    * Master mode baud rate divisor. Values can be even numbers in the range
188    * [2-32] inclusive. */
189   uint8_t                    divisor;
190 } QSPI_Init_TypeDef;
191 
192 /** Default configuration for QSPI_Init_TypeDef structure. */
193 #define QSPI_INIT_DEFAULT                               \
194   {                                                     \
195     true,                /* Enable Quad SPI. */         \
196     32,                  /* Divide QSPI clock by 32. */ \
197   }
198 
199 /*******************************************************************************
200  ******************************   PROTOTYPES   *********************************
201  ******************************************************************************/
202 
203 void QSPI_Init(QSPI_TypeDef * qspi, const QSPI_Init_TypeDef * init);
204 void QSPI_ReadConfig(QSPI_TypeDef * qspi, const QSPI_ReadConfig_TypeDef * config);
205 void QSPI_WriteConfig(QSPI_TypeDef * qspi, const QSPI_WriteConfig_TypeDef * config);
206 void QSPI_ExecStigCmd(QSPI_TypeDef * qspi, const QSPI_StigCmd_TypeDef * stigCmd);
207 
208 /***************************************************************************//**
209  * @brief
210  *   Wait for the QSPI to go into idle state.
211  *
212  * @param[in] qspi
213  *   Pointer to QSPI peripheral register block.
214  ******************************************************************************/
QSPI_WaitForIdle(QSPI_TypeDef * qspi)215 __STATIC_INLINE void QSPI_WaitForIdle(QSPI_TypeDef * qspi)
216 {
217   while ((qspi->CONFIG & _QSPI_CONFIG_IDLE_MASK) == 0)
218     ;
219 }
220 
221 /***************************************************************************//**
222  * @brief
223  *   Get the fill level of the write partition of the QSPI internal SRAM.
224  *
225  * @param[in] qspi
226  *   Pointer to QSPI peripheral register block.
227  *
228  * @return
229  *   SRAM fill level of the write partition. The value is the number of 4 byte
230  *   words in the write partition.
231  ******************************************************************************/
QSPI_GetWriteLevel(QSPI_TypeDef * qspi)232 __STATIC_INLINE uint16_t QSPI_GetWriteLevel(QSPI_TypeDef * qspi)
233 {
234   return (qspi->SRAMFILL & _QSPI_SRAMFILL_SRAMFILLINDACWRITE_MASK)
235          >> _QSPI_SRAMFILL_SRAMFILLINDACWRITE_SHIFT;
236 }
237 
238 /***************************************************************************//**
239  * @brief
240  *   Get the fill level of the read partition of the QSPI internal SRAM.
241  *
242  * @param[in] qspi
243  *   Pointer to QSPI peripheral register block.
244  *
245  * @return
246  *   SRAM fill level of the read partition. The value is the number of 4 byte
247  *   words in the read partition.
248  ******************************************************************************/
QSPI_GetReadLevel(QSPI_TypeDef * qspi)249 __STATIC_INLINE uint16_t QSPI_GetReadLevel(QSPI_TypeDef * qspi)
250 {
251   return (qspi->SRAMFILL & _QSPI_SRAMFILL_SRAMFILLINDACREAD_MASK)
252          >> _QSPI_SRAMFILL_SRAMFILLINDACREAD_SHIFT;
253 }
254 
255 /***************************************************************************//**
256  * @brief
257  *   Enable/disable Quad SPI.
258  *
259  * @param[in] qspi
260  *   Pointer to QSPI peripheral register block.
261  *
262  * @param[in] enable
263  *   true to enable Quad SPI, false to disable Quad SPI.
264  ******************************************************************************/
QSPI_Enable(QSPI_TypeDef * qspi,bool enable)265 __STATIC_INLINE void QSPI_Enable(QSPI_TypeDef * qspi, bool enable)
266 {
267   BUS_RegBitWrite(&qspi->CONFIG, _QSPI_CONFIG_ENBSPI_SHIFT, enable ? 1 : 0);
268 }
269 
270 /***************************************************************************//**
271  * @brief
272  *   Get the current interrupt flags.
273  *
274  * @param[in] qspi
275  *   Pointer to QSPI peripheral register block.
276  *
277  * @return
278  *   This functions returns the current interrupt flags that are set.
279  ******************************************************************************/
QSPI_IntGet(QSPI_TypeDef * qspi)280 __STATIC_INLINE uint32_t QSPI_IntGet(QSPI_TypeDef * qspi)
281 {
282   return qspi->IRQSTATUS;
283 }
284 
285 /***************************************************************************//**
286  * @brief
287  *   Clear interrupt flags.
288  *
289  * @param[in] qspi
290  *   Pointer to QSPI peripheral register block.
291  *
292  * @param[in] flags
293  *   The interrupt flags to clear.
294  ******************************************************************************/
QSPI_IntClear(QSPI_TypeDef * qspi,uint32_t flags)295 __STATIC_INLINE void QSPI_IntClear(QSPI_TypeDef * qspi, uint32_t flags)
296 {
297   qspi->IRQSTATUS = flags;
298 }
299 
300 /***************************************************************************//**
301  * @brief
302  *   Enable interrupts.
303  *
304  * @param[in] qspi
305  *   Pointer to QSPI peripheral register block.
306  *
307  * @param[in] flags
308  *   The interrupt flags to enable.
309  ******************************************************************************/
QSPI_IntEnable(QSPI_TypeDef * qspi,uint32_t flags)310 __STATIC_INLINE void QSPI_IntEnable(QSPI_TypeDef * qspi, uint32_t flags)
311 {
312   qspi->IRQMASK = flags & (~_QSPI_IRQMASK_MASK);
313 }
314 
315 /***************************************************************************//**
316  * @brief
317  *   Disable interrupts.
318  *
319  * @param[in] qspi
320  *   Pointer to QSPI peripheral register block.
321  *
322  * @param[in] flags
323  *   The interrupt flags to disable.
324  ******************************************************************************/
QSPI_IntDisable(QSPI_TypeDef * qspi,uint32_t flags)325 __STATIC_INLINE void QSPI_IntDisable(QSPI_TypeDef * qspi, uint32_t flags)
326 {
327   qspi->IRQMASK = ~flags & (~_QSPI_IRQMASK_MASK);
328 }
329 
330 /** @} (end addtogroup qspi) */
331 
332 #ifdef __cplusplus
333 }
334 #endif
335 
336 #endif /* defined(QSPI_COUNT) && (QSPI_COUNT > 0) */
337 #endif /* EM_QSPI_H */
338