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