1 /***************************************************************************//**
2 * \file cy_smif_memslot.c
3 * \version 2.60
4 *
5 * \brief
6 *  This file provides the source code for the memory-level APIs of the SMIF driver.
7 *
8 * Note:
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2016-2022 Cypress Semiconductor Corporation
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 *     http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27 
28 #include "cy_device.h"
29 
30 #if defined (CY_IP_MXSMIF)
31 
32 #include "cy_smif_memslot.h"
33 #include "cy_gpio.h"
34 
35 #if defined(__cplusplus)
36 extern "C" {
37 #endif
38 
39 /** \cond INTERNAL */
40 /***************************************
41 *     Internal Constants
42 ***************************************/
43 #define SMIF_MAX_RX_COUNT           (65536UL)
44 #define ONE_MILLI_IN_MICRO          (1000UL)
45 #define TIMEOUT_SLICE_MAX           (1000000UL)    /* The maximum timeout slice (microseconds)
46                                                     * while polling the memory */
47 #define TIMEOUT_SLICE_DIV           (4U)           /* The division factor to use for slicing the timeout
48                                                     * while polling the memory
49                                                     */
50 #if (CY_IP_MXSMIF_VERSION>=2)
51 static cy_en_smif_status_t cy_smif_octalddrenable(SMIF_Type *base,
52                                     cy_stc_smif_mem_config_t const *memDevice,
53                                     cy_stc_smif_context_t const *context);
54 #endif
55 /** \endcond */
56 
57 /*******************************************************************************
58 * Function Name: Cy_SMIF_MemInit
59 ****************************************************************************//**
60 *
61 * This function initializes the slots of the memory device in the SMIF
62 * configuration.
63 * This function must be called when a memory device is required to be used
64 * in memory-mapped (XIP) mode. This function can also be called instead of
65 * calling \ref Cy_SMIF_MemSfdpDetect when SFDP auto-discovery is enabled.
66 * Note that this function performs SFDP on all the external memories whereas
67 * \ref Cy_SMIF_MemSfdpDetect performs it only on one memory that is specified
68 * through the arguments. This function configures the SMIF device slot registers
69 * with the configuration from \ref cy_stc_smif_mem_config_t structure which is
70 * a member of the \ref cy_stc_smif_block_config_t structure. If SFDP discovery
71 * is enabled in the configuration structure through autoDetectSfdp field,
72 * this function calls \ref Cy_SMIF_MemSfdpDetect function for each memory,
73 * fills the structures with the discovered parameters, and configures the
74 * SMIF device slot registers accordingly. \ref Cy_SMIF_Init must have been
75 * called prior to calling this function.
76 * The \ref cy_stc_smif_context_t context structure returned from \ref Cy_SMIF_Init
77 * is passed as a parameter to this function.
78 *
79 * \note 4-byte addressing mode is set when the memory device supports
80 *       3- or 4-byte addressing mode.
81 *
82 * \param base
83 * The address of the slave-slot device register to initialize.
84 *
85 * \param blockConfig
86 * The configuration structure array that configures the SMIF memory device to be
87 * mapped into the PSoC memory map. \ref cy_stc_smif_mem_config_t
88 *
89 * \param context
90 * This is the pointer to the context structure \ref cy_stc_smif_context_t
91 * allocated by the user. The structure is used during the SMIF
92 * operation for internal configuration and data retention. The user must not
93 * modify anything in this structure.
94 *
95 * \return The memory slot initialization status.
96 *       - \ref CY_SMIF_SUCCESS
97 *       - \ref CY_SMIF_BAD_PARAM
98 *       - \ref CY_SMIF_SFDP_SS0_FAILED
99 *       - \ref CY_SMIF_SFDP_SS1_FAILED
100 *       - \ref CY_SMIF_SFDP_SS2_FAILED
101 *       - \ref CY_SMIF_SFDP_SS3_FAILED
102 *
103 *******************************************************************************/
Cy_SMIF_MemInit(SMIF_Type * base,cy_stc_smif_block_config_t const * blockConfig,cy_stc_smif_context_t * context)104 cy_en_smif_status_t Cy_SMIF_MemInit(SMIF_Type *base,
105                             cy_stc_smif_block_config_t const * blockConfig,
106                             cy_stc_smif_context_t *context)
107 {
108     SMIF_DEVICE_Type volatile * device;
109     cy_stc_smif_mem_config_t const * memCfg;
110     uint32_t result = (uint32_t)CY_SMIF_BAD_PARAM;
111     uint32_t sfdpRes =(uint32_t)CY_SMIF_SUCCESS;
112     uint32_t idx;
113 
114     if ((NULL != base) && (NULL != blockConfig) && (NULL != blockConfig->memConfig)
115         && (NULL != context) && (0U != blockConfig->memCount))
116     {
117         uint32_t size = blockConfig->memCount;
118         cy_stc_smif_mem_config_t** extMemCfg = blockConfig->memConfig;
119 
120         result = (uint32_t)CY_SMIF_SUCCESS;
121         for(idx = 0UL; idx < size; idx++)
122         {
123             memCfg = extMemCfg[idx];
124             if (NULL != memCfg)
125             {
126                 /* Check smif memory slot configuration */
127                 CY_ASSERT_L3(CY_SMIF_SLAVE_SEL_VALID(memCfg->slaveSelect));
128                 CY_ASSERT_L3(CY_SMIF_DATA_SEL_VALID(memCfg->dataSelect));
129 
130                 #if (CY_IP_MXSMIF_VERSION >= 2)
131                 context->flags = memCfg->flags;
132                 #endif /* (CY_IP_MXSMIF_VERSION>=2) */
133 
134                 /* SPI(deviceCfg) and Hyperbus(hbdeviceCfg) are mutually exclusive and if both are initialized, priority would be for SPI(deviceCfg) */
135                 if(memCfg->deviceCfg != NULL)
136                 {
137                     device = Cy_SMIF_GetDeviceBySlot(base, memCfg->slaveSelect);
138                     if (NULL != device)
139                     {
140                         /* The slave-slot initialization of the device control register.
141                          * Cy_SMIF_MemSfdpDetect() must work */
142                         SMIF_DEVICE_CTL(device)  = _CLR_SET_FLD32U(SMIF_DEVICE_CTL(device),
143                                                                    SMIF_DEVICE_CTL_DATA_SEL,
144                                                                   (uint32_t)memCfg->dataSelect);
145 
146                         /* Before SFDP Enumeration, configure SMIF dedicated Clock and RWDS lines */
147                         #if (CY_IP_MXSMIF_VERSION >= 5)
148                         SMIF_CLK_HSIOM(base) = ((uint32_t)(HSIOM_SEL_ACT_15)) | (((uint32_t)HSIOM_SEL_ACT_15) << 8U);
149                         SMIF_RWDS_HSIOM(base) = (uint32_t)HSIOM_SEL_ACT_15;
150                         SMIF_CLK_DRIVEMODE(base) = CY_GPIO_DM_STRONG | (CY_GPIO_DM_STRONG << 4U);
151                         SMIF_RWDS_DRIVEMODE(base) = CY_GPIO_DM_PULLDOWN;
152                         #endif
153 
154                         uint32_t sfdpRet = (uint32_t)CY_SMIF_SUCCESS;
155                         if (0U != (memCfg->flags & CY_SMIF_FLAG_DETECT_SFDP))
156                         {
157                             sfdpRet = (uint32_t)Cy_SMIF_MemSfdpDetect(base,
158                                                     memCfg->deviceCfg,
159                                                     memCfg->slaveSelect,
160                                                     memCfg->dataSelect,
161                                                     context);
162                             if((uint32_t)CY_SMIF_SUCCESS != sfdpRet)
163                             {
164                                 sfdpRes |=  ((uint32_t)CY_SMIF_SFDP_FAIL << idx);
165                             }
166                         }
167                         /* Check the size of the smif memory slot address */
168                         CY_ASSERT_L2(MEM_ADDR_SIZE_VALID(memCfg->deviceCfg->numOfAddrBytes));
169 
170                         /* Check if SMIF XIP is already enabled, then do not overwrite XIP registers */
171                         if (((uint32_t)CY_SMIF_SUCCESS == sfdpRet) &&
172                              (0U != (memCfg->flags & CY_SMIF_FLAG_MEMORY_MAPPED)) &&
173                              (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 1U))
174                         {
175                             /* Check valid parameters for XIP */
176                             CY_ASSERT_L3(MEM_ADDR_VALID( memCfg->baseAddress, memCfg->memMappedSize));
177                             CY_ASSERT_L3(MEM_MAPPED_SIZE_VALID( memCfg->memMappedSize));
178 
179                             XipRegInit(device, memCfg);
180 
181     #if(CY_IP_MXSMIF_VERSION>=2)
182                             context->preXIPDataRate = memCfg->deviceCfg->readCmd->dataRate;
183     #endif /* CY_IP_MXSMIF_VERSION */
184 
185                             /* The device control register initialization */
186                             SMIF_DEVICE_CTL(device) = _VAL2FLD(SMIF_DEVICE_CTL_WR_EN, ((bool)(memCfg->flags & CY_SMIF_FLAG_WRITE_ENABLE))? 1U : 0U) |
187                                           _VAL2FLD(SMIF_DEVICE_CTL_CRYPTO_EN, ((bool)(memCfg->flags & CY_SMIF_FLAG_CRYPTO_ENABLE))? 1U : 0U) |
188                                           _VAL2FLD(SMIF_DEVICE_CTL_DATA_SEL,  (uint32_t)memCfg->dataSelect) |
189     #if(CY_IP_MXSMIF_VERSION>=2)
190                                           _VAL2FLD(SMIF_DEVICE_CTL_MERGE_EN,  ((bool)(memCfg->flags & CY_SMIF_FLAG_MERGE_ENABLE))? 1U : 0U)  |
191                                           _VAL2FLD(SMIF_DEVICE_CTL_MERGE_TIMEOUT,  (uint32_t)memCfg->mergeTimeout) |
192     #endif /* CY_IP_MXSMIF_VERSION */
193                                           SMIF_DEVICE_CTL_ENABLED_Msk;
194                         }
195                     }
196                     else
197                     {
198                         result = (uint32_t)CY_SMIF_BAD_PARAM;
199                         break;
200                     }
201                 }
202     #if (CY_IP_MXSMIF_VERSION>=2) && defined (SMIF_HYPERBUS_DEVICE_SUPPORT)
203                 else if(memCfg->hbdeviceCfg != NULL)
204                 {
205                     result = (uint32_t)Cy_SMIF_HyperBus_InitDevice(base, memCfg, context);
206                 }
207     #endif /* (CY_IP_MXSMIF_VERSION>=2) && defined (SMIF_HYPERBUS_DEVICE_SUPPORT) */
208                 else
209                 {
210                     result = (uint32_t)CY_SMIF_BAD_PARAM;
211                     break;
212                 }
213             }
214         }
215     }
216     if((uint32_t)CY_SMIF_SUCCESS != sfdpRes)
217     {
218         result = (((uint32_t)CY_SMIF_ID) | ((uint32_t)CY_PDL_STATUS_ERROR) | sfdpRes);
219     }
220     return (cy_en_smif_status_t) result;
221 }
222 
223 /*******************************************************************************
224 * Function Name: Cy_SMIF_MemDeInit
225 ****************************************************************************//**
226 *
227 * This function de-initializes all slave slots of the memory device to their default
228 * values.
229 *
230 * \param base
231 * Holds the base address of the SMIF block registers.
232 *
233 *******************************************************************************/
Cy_SMIF_MemDeInit(SMIF_Type * base)234 void Cy_SMIF_MemDeInit(SMIF_Type *base)
235 {
236     /* Configure the SMIF device slots to the default values. The default value is 0 */
237     uint32_t deviceIndex;
238 
239 #if (CY_IP_MXSMIF_VERSION >= 5)
240     SMIF_CLK_HSIOM(base) = (uint32_t)HSIOM_SEL_GPIO;
241     SMIF_RWDS_HSIOM(base) = (uint32_t)HSIOM_SEL_GPIO;
242     SMIF_CLK_DRIVEMODE(base) = CY_GPIO_DM_ANALOG | (CY_GPIO_DM_ANALOG << 8U);
243     SMIF_RWDS_DRIVEMODE(base) = CY_GPIO_DM_ANALOG;
244 #endif
245 
246     for(deviceIndex = 0UL; deviceIndex < (uint32_t)SMIF_DEVICE_NR; deviceIndex++)
247     {
248         SMIF_DEVICE_IDX_CTL(base, deviceIndex)           = 0U;
249         SMIF_DEVICE_IDX_ADDR(base, deviceIndex)          = 0U;
250         SMIF_DEVICE_IDX_MASK(base, deviceIndex)          = 0U;
251         SMIF_DEVICE_IDX_ADDR_CTL(base, deviceIndex)      = 0U;
252         SMIF_DEVICE_IDX_RD_CMD_CTL(base, deviceIndex)    = 0U;
253         SMIF_DEVICE_IDX_RD_ADDR_CTL(base, deviceIndex)   = 0U;
254         SMIF_DEVICE_IDX_RD_MODE_CTL(base, deviceIndex)   = 0U;
255         SMIF_DEVICE_IDX_RD_DUMMY_CTL(base, deviceIndex)  = 0U;
256         SMIF_DEVICE_IDX_RD_DATA_CTL(base, deviceIndex)   = 0U;
257         SMIF_DEVICE_IDX_WR_CMD_CTL(base, deviceIndex)    = 0U;
258         SMIF_DEVICE_IDX_WR_ADDR_CTL(base, deviceIndex)   = 0U;
259         SMIF_DEVICE_IDX_WR_MODE_CTL(base, deviceIndex)   = 0U;
260         SMIF_DEVICE_IDX_WR_DUMMY_CTL(base, deviceIndex)  = 0U;
261         SMIF_DEVICE_IDX_WR_DATA_CTL(base, deviceIndex)   = 0U;
262     }
263 }
264 
265 
266 /*******************************************************************************
267 * Function Name: Cy_SMIF_MemCmdWriteEnable
268 ****************************************************************************//**
269 *
270 * This function sends the Write Enable command to the memory device.
271 *
272 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
273 * The Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
274 * this API is called for each memory.
275 *
276 * \param base
277 * Holds the base address of the SMIF block registers.
278 *
279 * \param memDevice
280 * The device to which the command is sent.
281 *
282 * \param context
283 * This is the pointer to the context structure \ref cy_stc_smif_context_t
284 * allocated by the user. The structure is used during the SMIF
285 * operation for internal configuration and data retention. The user must not
286 * modify anything in this structure.
287 *
288 * \return A status of the command transmission.
289 *       - \ref CY_SMIF_SUCCESS
290 *       - \ref CY_SMIF_EXCEED_TIMEOUT
291 *       - \ref CY_SMIF_CMD_NOT_FOUND
292 *
293 *******************************************************************************/
Cy_SMIF_MemCmdWriteEnable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)294 cy_en_smif_status_t Cy_SMIF_MemCmdWriteEnable(SMIF_Type *base,
295                                         cy_stc_smif_mem_config_t const *memDevice,
296                                         cy_stc_smif_context_t const *context)
297 {
298     /* The memory Write Enable */
299     cy_stc_smif_mem_cmd_t* writeEn = memDevice->deviceCfg->writeEnCmd;
300 
301     cy_en_smif_status_t result = CY_SMIF_CMD_NOT_FOUND;
302 
303     if(NULL != writeEn)
304     {
305 #if (CY_IP_MXSMIF_VERSION>=2)
306         result = Cy_SMIF_TransmitCommand_Ext( base,
307                                 (uint16_t)(writeEn->command | writeEn->command << 8),
308                                 (writeEn->cmdWidth == CY_SMIF_WIDTH_OCTAL) ? true : false,
309                                 writeEn->cmdWidth,
310                                 writeEn->cmdRate,
311                                 NULL,
312                                 0,
313                                 CY_SMIF_WIDTH_NA,
314                                 writeEn->addrRate,
315                                 memDevice->slaveSelect,
316                                 CY_SMIF_TX_LAST_BYTE,
317                                 context);
318 #else
319         result = Cy_SMIF_TransmitCommand( base, (uint8_t) writeEn->command,
320                                         writeEn->cmdWidth,
321                                         NULL,
322                                         CY_SMIF_CMD_WITHOUT_PARAM,
323                                         CY_SMIF_WIDTH_NA,
324                                         memDevice->slaveSelect,
325                                         CY_SMIF_TX_LAST_BYTE,
326                                         context);
327 #endif
328     }
329 
330     return result;
331 }
332 
333 
334 /*******************************************************************************
335 * Function Name: Cy_SMIF_MemCmdWriteDisable
336 ****************************************************************************//**
337 *
338 * This function sends a Write Disable command to the memory device.
339 *
340 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
341 * Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode
342 * this API should be called for each memory.
343 *
344 * \param base
345 * Holds the base address of the SMIF block registers.
346 *
347 * \param memDevice
348 * The device to which the command is sent.
349 *
350 * \param context
351 * This is the pointer to the context structure \ref cy_stc_smif_context_t
352 * allocated by the user. The structure is used during the SMIF
353 * operation for internal configuration and data retention. The user must not
354 * modify anything in this structure.
355 *
356 * \return A status of the command transmission.
357 *       - \ref CY_SMIF_SUCCESS
358 *       - \ref CY_SMIF_EXCEED_TIMEOUT
359 *       - \ref CY_SMIF_CMD_NOT_FOUND
360 *
361 *******************************************************************************/
Cy_SMIF_MemCmdWriteDisable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)362 cy_en_smif_status_t Cy_SMIF_MemCmdWriteDisable(SMIF_Type *base,
363                                     cy_stc_smif_mem_config_t const *memDevice,
364                                     cy_stc_smif_context_t const *context)
365 {
366     cy_stc_smif_mem_cmd_t* writeDis = memDevice->deviceCfg->writeDisCmd;
367 
368     cy_en_smif_status_t result = CY_SMIF_CMD_NOT_FOUND;
369 
370     if(NULL != writeDis)
371     {
372 #if (CY_IP_MXSMIF_VERSION>=2)
373         result = Cy_SMIF_TransmitCommand_Ext( base,
374                                 (uint16_t)(writeDis->command | writeDis->command << 8),
375                                 (writeDis->cmdWidth == CY_SMIF_WIDTH_OCTAL) ? true : false,
376                                 writeDis->cmdWidth,
377                                 writeDis->cmdRate,
378                                 NULL,
379                                 0,
380                                 CY_SMIF_WIDTH_NA,
381                                 writeDis->addrRate,
382                                 memDevice->slaveSelect,
383                                 CY_SMIF_TX_LAST_BYTE,
384                                 context);
385 #else
386         /* The memory write disable */
387         result = Cy_SMIF_TransmitCommand( base, (uint8_t)writeDis->command,
388                                           writeDis->cmdWidth,
389                                           NULL,
390                                           CY_SMIF_CMD_WITHOUT_PARAM,
391                                           CY_SMIF_WIDTH_NA,
392                                           memDevice->slaveSelect,
393                                           CY_SMIF_TX_LAST_BYTE,
394                                           context);
395 #endif
396     }
397 
398     return result;
399 }
400 
401 
402 /*******************************************************************************
403 * Function Name: Cy_SMIF_MemIsBusy
404 ****************************************************************************//**
405 *
406 * This function checks if the status of the memory device is busy.
407 * This is done by reading the status register and the corresponding bit
408 * (stsRegBusyMask). This function is a blocking function until the status
409 * register from the memory is read.
410 *
411 * \note In the dual quad mode, this API is called for each memory.
412 *
413 * \param base
414 * Holds the base address of the SMIF block registers.
415 *
416 * \param memDevice
417 *  The device to which the command is sent.
418 *
419 * \param context
420 * This is the pointer to the context structure \ref cy_stc_smif_context_t
421 * allocated by the user. The structure is used during the SMIF
422 * operation for internal configuration and data retention. The user must not
423 * modify anything in this structure.
424 *
425 * \return A status of the memory device.
426 *       - True - The device is busy or a timeout occurs.
427 *       - False - The device is not busy.
428 *
429 * \note Check \ref group_smif_usage_rules for any usage restriction
430 *
431 *******************************************************************************/
Cy_SMIF_MemIsBusy(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)432 bool Cy_SMIF_MemIsBusy(SMIF_Type *base, cy_stc_smif_mem_config_t const *memDevice,
433                             cy_stc_smif_context_t const *context)
434 {
435     uint16_t  status = 1U;
436     cy_en_smif_status_t readStsResult = CY_SMIF_CMD_NOT_FOUND;
437     cy_stc_smif_mem_device_cfg_t* device =  memDevice->deviceCfg;
438 
439     if(NULL != device->readStsRegWipCmd)
440     {
441 #if (CY_IP_MXSMIF_VERSION>=2)
442         if (device->readStsRegWipCmd->cmdWidth == CY_SMIF_WIDTH_OCTAL)
443         {
444             uint8_t addr_param[4] = {0};
445             /* Read the memory status register */
446             readStsResult = Cy_SMIF_TransmitCommand_Ext( base,
447                         (uint16_t)(device->readStsRegWipCmd->command | (device->readStsRegWipCmd->command << 8)),
448                         true,
449                         device->readStsRegWipCmd->cmdWidth,
450                         device->readStsRegWipCmd->cmdRate,
451                         addr_param, sizeof(addr_param),
452                         device->readStsRegWipCmd->addrWidth,
453                         device->readStsRegWipCmd->addrRate,
454                         memDevice->slaveSelect,
455                         CY_SMIF_TX_NOT_LAST_BYTE,
456                         context);
457 
458             if ((CY_SMIF_SUCCESS == readStsResult) &&  (device->readStsRegWipCmd->dummyCycles > 0U))
459             {
460                 readStsResult = Cy_SMIF_SendDummyCycles_Ext(base,
461                     device->readStsRegWipCmd->addrWidth,
462                     device->readStsRegWipCmd->addrRate,
463                     device->readStsRegWipCmd->dummyCycles);
464             }
465             if (CY_SMIF_SUCCESS == readStsResult)
466             {
467                 readStsResult = Cy_SMIF_ReceiveDataBlocking_Ext( base, (uint8_t *)&status,
468                                         (device->readStsRegWipCmd->cmdRate == CY_SMIF_DDR) ? 2U : 1U,
469                                            device->readStsRegWipCmd->cmdWidth,
470                                            device->readStsRegWipCmd->cmdRate,
471                                            context);
472             }
473 
474         }
475         else
476         {
477 #endif
478             readStsResult = Cy_SMIF_MemCmdReadStatus(base, memDevice,  (uint8_t *)&status,
479                             (uint8_t)device->readStsRegWipCmd->command,
480                             context);
481 #if (CY_IP_MXSMIF_VERSION>=2)
482         }
483 #endif
484     }
485 
486     if (CY_SMIF_SUCCESS == readStsResult)
487     {
488         /* Masked not busy bits in returned status */
489         status &= (uint8_t)device->stsRegBusyMask;
490     }
491 
492     return (0U != status);
493 }
494 
495 
496 /*******************************************************************************
497 * Function Name: Cy_SMIF_MemQuadEnable
498 ****************************************************************************//**
499 *
500 * This function enables the memory device for the quad mode of operation.
501 * This command must be executed before sending quad SPI commands to the
502 * memory device.
503 *
504 * \note In the dual quad mode, this API is called for each memory.
505 *
506 * \param base
507 * Holds the base address of the SMIF block registers.
508 *
509 * \param memDevice
510 * The device to which the command is sent.
511 *
512 * \param context
513 * This is the pointer to the context structure \ref cy_stc_smif_context_t
514 * allocated by the user. The structure is used during the SMIF
515 * operation for internal configuration and data retention. The user must not
516 * modify anything in this structure.
517 *
518 * \return A status of the command.
519 *   - \ref CY_SMIF_SUCCESS
520 *   - \ref CY_SMIF_NO_QE_BIT
521 *   - \ref CY_SMIF_CMD_FIFO_FULL
522 *   - \ref CY_SMIF_BAD_PARAM
523 *   - \ref CY_SMIF_CMD_NOT_FOUND
524 *
525 * \note Check \ref group_smif_usage_rules for any usage restriction
526 *
527 *******************************************************************************/
Cy_SMIF_MemQuadEnable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)528 cy_en_smif_status_t Cy_SMIF_MemQuadEnable(SMIF_Type *base,
529                                     cy_stc_smif_mem_config_t const *memDevice,
530                                     cy_stc_smif_context_t const *context)
531 {
532     cy_en_smif_status_t result= CY_SMIF_CMD_NOT_FOUND;
533     uint8_t statusReg[CY_SMIF_QE_BIT_STATUS_REG2_T1] = {0U};
534     cy_stc_smif_mem_device_cfg_t* device =  memDevice->deviceCfg;
535 
536     /* Check that command exists */
537     if((NULL != device->readStsRegQeCmd)  &&
538        (NULL != device->writeStsRegQeCmd) &&
539        (NULL != device->readStsRegWipCmd))
540     {
541         uint8_t readQeCmd  = (uint8_t)device->readStsRegQeCmd->command;
542         uint8_t writeQeCmd = (uint8_t)device->writeStsRegQeCmd->command;
543         uint8_t readWipCmd = (uint8_t)device->readStsRegWipCmd->command;
544 
545         result = Cy_SMIF_MemCmdReadStatus(base, memDevice, &statusReg[0U],
546                     readQeCmd, context);
547         if (CY_SMIF_SUCCESS == result)
548         {
549             uint32_t qeMask = device->stsRegQuadEnableMask;
550 
551             switch(qeMask)
552             {
553                 case CY_SMIF_SFDP_QE_BIT_6_OF_SR_1:
554                     statusReg[0U] |= (uint8_t)qeMask;
555                     result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
556                                 &statusReg[0U], writeQeCmd, context);
557                     break;
558                 case CY_SMIF_SFDP_QE_BIT_1_OF_SR_2:
559                     /* Read status register 1 with the assumption that WIP is always in
560                     * status register 1 */
561                     result = Cy_SMIF_MemCmdReadStatus(base, memDevice,
562                                 &statusReg[0U], readWipCmd, context);
563                     if (CY_SMIF_SUCCESS == result)
564                     {
565                         result = Cy_SMIF_MemCmdReadStatus(base, memDevice,
566                                     &statusReg[1U], readQeCmd, context);
567                         if (CY_SMIF_SUCCESS == result)
568                         {
569                             statusReg[1U] |= (uint8_t)qeMask;
570 
571                             if (writeQeCmd == CY_SMIF_WRITE_STATUS_REG2_T2_CMD)
572                             {
573                                 result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
574                                         &statusReg[1U], writeQeCmd, context);
575                             }
576                             else
577                             {
578                                 result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
579                                         statusReg, writeQeCmd, context);
580                             }
581                         }
582                     }
583                     break;
584                 case CY_SMIF_SFDP_QE_BIT_7_OF_SR_2:
585                     result = Cy_SMIF_MemCmdReadStatus(base, memDevice,
586                                 &statusReg[1U], readQeCmd, context);
587                     if (CY_SMIF_SUCCESS == result)
588                     {
589                         statusReg[1U] |= (uint8_t)qeMask;
590                         result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
591                                     &statusReg[1U], writeQeCmd, context);
592                     }
593                     break;
594                 default:
595                     result = CY_SMIF_NO_QE_BIT;
596                     break;
597             }
598         }
599     }
600     return(result);
601 }
602 #if (CY_IP_MXSMIF_VERSION>=2) || defined (CY_DOXYGEN)
603 /*******************************************************************************
604 * Function Name: Cy_SMIF_MemOctalEnable
605 ****************************************************************************//**
606 *
607 * This function enables the memory device for the octal mode of operation.
608 * This command must be executed before sending octal SPI commands to the
609 * memory device.
610 *
611 * \param base
612 * Holds the base address of the SMIF block registers.
613 *
614 * \param memDevice
615 * The device to which the command is sent.
616 *
617 * \param dataRate
618 * Specifies the data rate to enable (SDR/DDR).
619 *
620 * \param context
621 * This is the pointer to the context structure \ref cy_stc_smif_context_t
622 * allocated by the user. The structure is used during the SMIF
623 * operation for internal configuration and data retention. The user must not
624 * modify anything in this structure.
625 *
626 * \return A status of the command.
627 *   - \ref CY_SMIF_SUCCESS
628 *   - \ref CY_SMIF_NO_OE_BIT
629 *   - \ref CY_SMIF_CMD_FIFO_FULL
630 *   - \ref CY_SMIF_BAD_PARAM
631 *   - \ref CY_SMIF_CMD_NOT_FOUND
632 *
633 * \note Check \ref group_smif_usage_rules for any usage restriction
634 *
635 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemOctalEnable
636 *******************************************************************************/
Cy_SMIF_MemOctalEnable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_en_smif_data_rate_t dataRate,cy_stc_smif_context_t const * context)637 cy_en_smif_status_t Cy_SMIF_MemOctalEnable(SMIF_Type *base,
638                                     cy_stc_smif_mem_config_t const *memDevice,
639                                     cy_en_smif_data_rate_t dataRate,
640                                     cy_stc_smif_context_t const *context)
641 {
642     cy_en_smif_status_t result= CY_SMIF_CMD_NOT_FOUND;
643     cy_stc_smif_mem_device_cfg_t* device =  memDevice->deviceCfg;
644 
645     if (dataRate == CY_SMIF_DDR)
646     {
647         return cy_smif_octalddrenable(base, memDevice, context);
648     }
649     /* Check that command exists */
650     if((NULL != device->readStsRegOeCmd)  &&
651        (NULL != device->writeStsRegOeCmd))
652     {
653         uint8_t readOeCmd  = (uint8_t)device->readStsRegOeCmd->command;
654         uint8_t writeOeCmd = (uint8_t)device->writeStsRegOeCmd->command;
655         uint8_t octalEnableAddr[5] = {0U};
656 
657         if (device->octalEnableRegAddr != CY_SMIF_NO_COMMAND_OR_MODE)
658         {
659             result = ReadAnyReg(base, memDevice->slaveSelect, &octalEnableAddr[4],
660                                     readOeCmd, 0, (uint8_t *)&device->octalEnableRegAddr,
661                                     4, context);
662 
663             if (CY_SMIF_SUCCESS == result)
664             {
665                 uint32_t oeMask = device->stsRegOctalEnableMask;
666 
667                 octalEnableAddr[4] |= (uint8_t)oeMask;
668 
669                 /* The Write Enable */
670                 result =  Cy_SMIF_MemCmdWriteEnable(base, memDevice, context);
671 
672                 /* The Write Status */
673                 if (CY_SMIF_SUCCESS == result)
674                 {
675                     octalEnableAddr[3] = (uint8_t) device->octalEnableRegAddr; /* only 8 bits are valid as per SFDP spec */
676 
677                     result = Cy_SMIF_TransmitCommand( base, writeOeCmd, CY_SMIF_WIDTH_SINGLE,
678                                 (uint8_t const *)octalEnableAddr, 5, CY_SMIF_WIDTH_SINGLE,
679                                 memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
680                 }
681             }
682         }
683         else
684         {
685             uint8_t statusReg = 0;
686             result = Cy_SMIF_MemCmdReadStatus(base, memDevice, &statusReg,
687                         readOeCmd, context);
688             if (CY_SMIF_SUCCESS == result)
689             {
690                 uint32_t oeMask = device->stsRegOctalEnableMask;
691 
692                 statusReg |= (uint8_t)oeMask;
693                 result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
694                              &statusReg, writeOeCmd, context);
695             }
696         }
697     }
698 
699     return(result);
700 }
701 #endif
702 #if (CY_IP_MXSMIF_VERSION>=2)
cy_smif_octalddrenable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)703 static cy_en_smif_status_t cy_smif_octalddrenable(SMIF_Type *base,
704                                     cy_stc_smif_mem_config_t const *memDevice,
705                                     cy_stc_smif_context_t const *context)
706 {
707     cy_en_smif_status_t result= CY_SMIF_CMD_NOT_FOUND;
708     cy_stc_smif_mem_device_cfg_t* device =  memDevice->deviceCfg;
709     cy_stc_smif_octal_ddr_en_seq_t* oDDREnSeq = device->octalDDREnableSeq;
710 
711     /* Check that command exists */
712     if ((oDDREnSeq != NULL) && (base != NULL) && (context != NULL))
713     {
714         /* Send Command Sequence 1 */
715         if (oDDREnSeq->cmdSeq1Len > 0U)
716         {
717             result = Cy_SMIF_TransmitCommand( base, oDDREnSeq->cmdSeq1[0], CY_SMIF_WIDTH_SINGLE,
718                         (uint8_t const *)&oDDREnSeq->cmdSeq1[1U],
719                         ((uint32_t)oDDREnSeq->cmdSeq1Len - 1U), CY_SMIF_WIDTH_SINGLE,
720                         memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
721         }
722         /* Send Command Sequence 2 */
723         if (oDDREnSeq->cmdSeq2Len > 0U)
724         {
725             result = Cy_SMIF_TransmitCommand( base, oDDREnSeq->cmdSeq2[0], CY_SMIF_WIDTH_SINGLE,
726                         (uint8_t const *)&oDDREnSeq->cmdSeq2[1U],
727                         ((uint32_t)oDDREnSeq->cmdSeq2Len - 1U), CY_SMIF_WIDTH_SINGLE,
728                         memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
729         }
730 
731 #if (CY_IP_MXSMIF_VERSION>=5)
732         /* Set the clock to xSPI mode */
733         Cy_SMIF_SetRxCaptureMode(base, CY_SMIF_SEL_XSPI_HYPERBUS_WITH_DQS);
734 #endif
735 
736         /* Change Write Enable to 16-bit Octal DDR */
737         device->writeEnCmd->commandH = CY_SMIF_WRITE_ENABLE_CMD;
738         device->writeEnCmd->cmdRate = CY_SMIF_DDR;
739         device->writeEnCmd->cmdWidth = CY_SMIF_WIDTH_OCTAL;
740         device->writeEnCmd->cmdPresence = CY_SMIF_PRESENT_2BYTE;
741 
742         /* Change Write Disable to 16-bit Octal DDR*/
743         device->writeDisCmd->commandH = CY_SMIF_WRITE_ENABLE_CMD;
744         device->writeDisCmd->cmdRate = CY_SMIF_DDR;
745         device->writeDisCmd->cmdWidth = CY_SMIF_WIDTH_OCTAL;
746         device->writeDisCmd->cmdPresence = CY_SMIF_PRESENT_2BYTE;
747 
748         /* Change Read WIP status register to 16-bit Octal DDR */
749         device->readStsRegWipCmd->commandH = CY_SMIF_READ_STATUS_REG1_CMD;
750         device->readStsRegWipCmd->cmdRate = CY_SMIF_DDR;
751         device->readStsRegWipCmd->cmdWidth = CY_SMIF_WIDTH_OCTAL;
752         device->readStsRegWipCmd->cmdPresence = CY_SMIF_PRESENT_2BYTE;
753         device->readStsRegWipCmd->addrRate = CY_SMIF_DDR;
754         device->readStsRegWipCmd->addrWidth = CY_SMIF_WIDTH_OCTAL;
755         device->readStsRegWipCmd->dummyCycles= 3;
756         device->readStsRegWipCmd->dummyCyclesPresence = CY_SMIF_PRESENT_2BYTE;
757 
758         /* Change Chip Erase command to 16-bit Octal DDR */
759         device->chipEraseCmd->commandH = CY_SMIF_CHIP_ERASE_CMD;
760         device->chipEraseCmd->cmdRate = CY_SMIF_DDR;
761         device->chipEraseCmd->cmdWidth = CY_SMIF_WIDTH_OCTAL;
762         device->chipEraseCmd->cmdPresence = CY_SMIF_PRESENT_2BYTE;
763 
764         /* Change Chip Erase command to 16-bit Octal DDR */
765         device->eraseCmd->commandH = CY_SMIF_CHIP_ERASE_CMD;
766         device->eraseCmd->cmdRate = CY_SMIF_DDR;
767         device->eraseCmd->cmdWidth = CY_SMIF_WIDTH_OCTAL;
768         device->eraseCmd->cmdPresence = CY_SMIF_PRESENT_2BYTE;
769         device->eraseCmd->addrRate = CY_SMIF_DDR;
770         device->eraseCmd->addrWidth = CY_SMIF_WIDTH_OCTAL;
771 
772         /* Change Program command to 16-bit Octal DDR */
773         device->programCmd->commandH = device->programCmd->command;
774         device->programCmd->cmdRate = CY_SMIF_DDR;
775         device->programCmd->cmdWidth = CY_SMIF_WIDTH_OCTAL;
776         device->programCmd->cmdPresence = CY_SMIF_PRESENT_2BYTE;
777         device->programCmd->addrRate = CY_SMIF_DDR;
778         device->programCmd->addrWidth = CY_SMIF_WIDTH_OCTAL;
779         device->programCmd->dataRate = CY_SMIF_DDR;
780         device->programCmd->dataWidth = CY_SMIF_WIDTH_OCTAL;
781     }
782     return(result);
783 }
784 #endif
785 /*******************************************************************************
786 * Function Name: Cy_SMIF_MemCmdReadStatus
787 ****************************************************************************//**
788 *
789 * This function reads the status register. This function is a blocking function,
790 * it will block the execution flow until the status register is read.
791 *
792 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
793 * the Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
794 * this API is called for each memory.
795 *
796 * \param base
797 * Holds the base address of the SMIF block registers.
798 *
799 * \param memDevice
800 * The device to which the command is sent.
801 *
802 * \param status
803 * The status register value returned by the external memory.
804 *
805 * \param command
806 * The command required to read the status/configuration register.
807 *
808 * \param context
809 * This is the pointer to the context structure \ref cy_stc_smif_context_t
810 * allocated by the user. The structure is used during the SMIF
811 * operation for internal configuration and data retention. The user must not
812 * modify anything in this structure.
813 *
814 * \return A status of the command reception.
815 *       - \ref CY_SMIF_SUCCESS
816 *       - \ref CY_SMIF_CMD_FIFO_FULL
817 *       - \ref CY_SMIF_EXCEED_TIMEOUT
818 *       - \ref CY_SMIF_CMD_NOT_FOUND
819 *
820 * \note Check \ref group_smif_usage_rules for any usage restriction
821 *
822 *******************************************************************************/
Cy_SMIF_MemCmdReadStatus(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,uint8_t * status,uint8_t command,cy_stc_smif_context_t const * context)823 cy_en_smif_status_t Cy_SMIF_MemCmdReadStatus(SMIF_Type *base,
824                                     cy_stc_smif_mem_config_t const *memDevice,
825                                     uint8_t *status,
826                                     uint8_t command,
827                                     cy_stc_smif_context_t const *context)
828 {
829     cy_en_smif_status_t result = CY_SMIF_CMD_NOT_FOUND;
830 
831     /* Read the memory status register */
832     result = Cy_SMIF_TransmitCommand( base, command, CY_SMIF_WIDTH_SINGLE,
833                 NULL, CY_SMIF_CMD_WITHOUT_PARAM,
834                 CY_SMIF_WIDTH_NA, memDevice->slaveSelect,
835                 CY_SMIF_TX_NOT_LAST_BYTE, context);
836 
837     if (CY_SMIF_SUCCESS == result)
838     {
839         result = Cy_SMIF_ReceiveDataBlocking( base, status,
840                     CY_SMIF_READ_ONE_BYTE, CY_SMIF_WIDTH_SINGLE, context);
841     }
842 
843     return(result);
844 }
845 
846 
847 /*******************************************************************************
848 * Function Name: Cy_SMIF_MemCmdWriteStatus
849 ****************************************************************************//**
850 *
851 * This function writes the status register. This is a blocking function, it will
852 * block the execution flow until the command transmission is completed.
853 *
854 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
855 * The Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
856 * this API is called for each memory.
857 *
858 * \param base
859 * Holds the base address of the SMIF block registers.
860 *
861 * \param memDevice
862 * The device to which the command is sent.
863 *
864 * \param status
865 * The status to write into the status register.
866 *
867 * \param command
868 * The command to write into the status/configuration register.
869 *
870 * \param context
871 * This is the pointer to the context structure \ref cy_stc_smif_context_t
872 * allocated by the user. The structure is used during the SMIF
873 * operation for internal configuration and data retention. The user must not
874 * modify anything in this structure.
875 *
876 * \return A status of the command transmission.
877 *       - \ref CY_SMIF_SUCCESS
878 *       - \ref CY_SMIF_EXCEED_TIMEOUT
879 *       - \ref CY_SMIF_CMD_NOT_FOUND
880 *
881 *******************************************************************************/
Cy_SMIF_MemCmdWriteStatus(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,void const * status,uint8_t command,cy_stc_smif_context_t const * context)882 cy_en_smif_status_t Cy_SMIF_MemCmdWriteStatus(SMIF_Type *base,
883                                     cy_stc_smif_mem_config_t const *memDevice,
884                                     void const *status,
885                                     uint8_t command,
886                                     cy_stc_smif_context_t const *context)
887 {
888     cy_en_smif_status_t result;
889 
890     /* The Write Enable */
891     result =  Cy_SMIF_MemCmdWriteEnable(base, memDevice, context);
892 
893     /* The Write Status */
894     if (CY_SMIF_SUCCESS == result)
895     {
896         uint32_t size;
897         uint32_t qeMask = memDevice->deviceCfg->stsRegQuadEnableMask;
898 
899         size = ( (CY_SMIF_SFDP_QE_BIT_1_OF_SR_2 == qeMask) && (memDevice->deviceCfg->writeStsRegQeCmd->command == CY_SMIF_WRITE_STATUS_REG1_CMD)) ?
900                   CY_SMIF_WRITE_TWO_BYTES:CY_SMIF_WRITE_ONE_BYTE;
901         result = Cy_SMIF_TransmitCommand( base, command, CY_SMIF_WIDTH_SINGLE,
902                     (uint8_t const *)status, size, CY_SMIF_WIDTH_SINGLE,
903                     memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
904     }
905 
906     return(result);
907 }
908 /*******************************************************************************
909 * Function Name: Cy_SMIF_MemCmdChipErase
910 ****************************************************************************//**
911 *
912 * This function performs a chip erase of the external memory. The Write Enable
913 * command is called before this API.
914 *
915 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
916 * Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
917 * this API is called for each memory.
918 *
919 * \param base
920 * Holds the base address of the SMIF block registers.
921 *
922 * \param memDevice
923 * The device to which the command is sent
924 *
925 * \param context
926 * This is the pointer to the context structure \ref cy_stc_smif_context_t
927 * allocated by the user. The structure is used during the SMIF
928 * operation for internal configuration and data retention. The user must not
929 * modify anything in this structure.
930 *
931 * \return A status of the command transmission.
932 *       - \ref CY_SMIF_SUCCESS
933 *       - \ref CY_SMIF_EXCEED_TIMEOUT
934 *       - \ref CY_SMIF_CMD_NOT_FOUND
935 *
936 *******************************************************************************/
Cy_SMIF_MemCmdChipErase(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)937 cy_en_smif_status_t Cy_SMIF_MemCmdChipErase(SMIF_Type *base,
938                 cy_stc_smif_mem_config_t const *memDevice,
939                 cy_stc_smif_context_t const *context)
940 {
941     cy_en_smif_status_t result= CY_SMIF_CMD_NOT_FOUND;
942 
943     cy_stc_smif_mem_cmd_t *cmdErase = memDevice->deviceCfg->chipEraseCmd;
944     if(NULL != cmdErase)
945     {
946         result = Cy_SMIF_TransmitCommand( base, (uint8_t)cmdErase->command,
947                 cmdErase->cmdWidth, NULL,
948                 CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
949                 memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
950     }
951 
952     return(result);
953 }
954 
955 
956 /*******************************************************************************
957 * Function Name: Cy_SMIF_MemCmdSectorErase
958 ****************************************************************************//**
959 *
960 * This function performs a block Erase of the external memory. The Write Enable
961 * command is called before this API.
962 *
963 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
964 * The Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
965 * this API is called for each memory.
966 *
967 * \param base
968 * Holds the base address of the SMIF block registers.
969 *
970 * \param memDevice
971 * The device to which the command is sent.
972 *
973 * \param sectorAddr
974 * The sector address to erase.
975 *
976 * \param context
977 * This is the pointer to the context structure \ref cy_stc_smif_context_t
978 * allocated by the user. The structure is used during the SMIF
979 * operation for internal configuration and data retention. The user must not
980 * modify anything in this structure.
981 *
982 * \return A status of the command transmission.
983 *       - \ref CY_SMIF_SUCCESS
984 *       - \ref CY_SMIF_BAD_PARAM
985 *       - \ref CY_SMIF_EXCEED_TIMEOUT
986 *       - \ref CY_SMIF_CMD_NOT_FOUND
987 *
988 *******************************************************************************/
Cy_SMIF_MemCmdSectorErase(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,uint8_t const * sectorAddr,cy_stc_smif_context_t const * context)989 cy_en_smif_status_t Cy_SMIF_MemCmdSectorErase(SMIF_Type *base,
990                                         cy_stc_smif_mem_config_t const *memDevice,
991                                         uint8_t const *sectorAddr,
992                                         cy_stc_smif_context_t const *context)
993 {
994     cy_en_smif_status_t result = CY_SMIF_BAD_PARAM;
995 
996     CY_ASSERT_L1(NULL != memDevice);
997 
998     if (NULL != sectorAddr)
999     {
1000         cy_stc_smif_mem_device_cfg_t *device = memDevice->deviceCfg;
1001         cy_stc_smif_mem_cmd_t *cmdErase = device->eraseCmd;
1002         cy_stc_smif_hybrid_region_info_t* hybrInfo = NULL;
1003 
1004         result = Cy_SMIF_MemLocateHybridRegion(memDevice, &hybrInfo,
1005                 ByteArrayToValue(sectorAddr, device->numOfAddrBytes));
1006 
1007         if ((NULL != cmdErase) && (CY_SMIF_WIDTH_NA != cmdErase->cmdWidth) && (result != CY_SMIF_BAD_PARAM))
1008         {
1009             uint16_t eraseCommand = (uint16_t)((result == CY_SMIF_SUCCESS) ? (hybrInfo->eraseCmd) : (cmdErase->command));
1010 #if (CY_IP_MXSMIF_VERSION>=2)
1011             if (device->eraseCmd->cmdWidth != CY_SMIF_WIDTH_OCTAL)
1012             {
1013 #endif
1014                 result = Cy_SMIF_TransmitCommand( base, (uint8_t)eraseCommand,
1015                         cmdErase->cmdWidth, sectorAddr, device->numOfAddrBytes,
1016                         cmdErase->cmdWidth, memDevice->slaveSelect,
1017                         CY_SMIF_TX_LAST_BYTE, context);
1018 
1019 #if (CY_IP_MXSMIF_VERSION>=2)
1020             }
1021             else
1022             {
1023                 result = Cy_SMIF_TransmitCommand_Ext( base, (eraseCommand | ((uint16_t)eraseCommand << 8)),
1024                     true,cmdErase->cmdWidth, cmdErase->cmdRate, sectorAddr, device->numOfAddrBytes,
1025                     cmdErase->cmdWidth, cmdErase->addrRate, memDevice->slaveSelect,
1026                     CY_SMIF_TX_LAST_BYTE, context);
1027 
1028             }
1029 #endif
1030         }
1031         else
1032         {
1033             result = CY_SMIF_CMD_NOT_FOUND;
1034         }
1035     }
1036     return(result);
1037 }
1038 
1039 
1040 /*******************************************************************************
1041 * Function Name: Cy_SMIF_MemCmdProgram
1042 ****************************************************************************//**
1043 *
1044 * This function performs the Program operation.
1045 *
1046 * \note This function uses the  Cy_SMIF_TransmitCommand() API.
1047 * The Cy_SMIF_TransmitCommand() API works in the blocking mode. In the dual quad mode,
1048 * this API works with both types of memory simultaneously.
1049 *
1050 * \param base
1051 * Holds the base address of the SMIF block registers.
1052 *
1053 * \param memDevice
1054 * The device to which the command is sent.
1055 *
1056 * \param addr
1057 * The address to program.
1058 *
1059 * \param writeBuff
1060 * The pointer to the data to program. If this pointer is a NULL, then the
1061 * function does not enable the interrupt. This use case is  typically used when
1062 * the FIFO is handled outside the interrupt and is managed in either a
1063 * polling-based code or a DMA. The user would handle the FIFO management
1064 * in a DMA or a polling-based code.
1065 * If the user provides a NULL pointer in this function and does not handle
1066 * the FIFO transaction, this could either stall or timeout the operation
1067 * \ref Cy_SMIF_TransmitData().
1068 *
1069 * \param size
1070 * The size of data to program. The user must ensure that the data size
1071 * does not exceed the page size.
1072 *
1073 * \param cmdCompleteCb
1074 * The callback function to call after the transfer completion. NULL interpreted
1075 * as no callback.
1076 *
1077 * \param context
1078 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1079 * allocated by the user. The structure is used during the SMIF
1080 * operation for internal configuration and data retention. The user must not
1081 * modify anything in this structure.
1082 *
1083 * \return A status of a transmission.
1084 *       - \ref CY_SMIF_SUCCESS
1085 *       - \ref CY_SMIF_CMD_FIFO_FULL
1086 *       - \ref CY_SMIF_BAD_PARAM
1087 *       - \ref CY_SMIF_EXCEED_TIMEOUT
1088 *       - \ref CY_SMIF_CMD_NOT_FOUND
1089 *
1090 *******************************************************************************/
Cy_SMIF_MemCmdProgram(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,uint8_t const * addr,uint8_t const * writeBuff,uint32_t size,cy_smif_event_cb_t cmdCompleteCb,cy_stc_smif_context_t * context)1091 cy_en_smif_status_t Cy_SMIF_MemCmdProgram(SMIF_Type *base,
1092                                     cy_stc_smif_mem_config_t const *memDevice,
1093                                     uint8_t const *addr,
1094                                     uint8_t const *writeBuff,
1095                                     uint32_t size,
1096                                     cy_smif_event_cb_t cmdCompleteCb,
1097                                     cy_stc_smif_context_t *context)
1098 {
1099     cy_en_smif_status_t result = CY_SMIF_SUCCESS;
1100     cy_en_smif_slave_select_t slaveSelected;
1101 
1102     cy_stc_smif_mem_device_cfg_t *device = memDevice->deviceCfg;
1103     cy_stc_smif_mem_cmd_t *cmdProg = device->programCmd;
1104 
1105     if(NULL == cmdProg)
1106     {
1107         result = CY_SMIF_CMD_NOT_FOUND;
1108     }
1109     else if ((NULL == addr) || (size > device->programSize))
1110     {
1111         result = CY_SMIF_BAD_PARAM;
1112     }
1113     else
1114     {
1115         slaveSelected = (0U == memDevice->dualQuadSlots)?  memDevice->slaveSelect :
1116                                                         (cy_en_smif_slave_select_t)memDevice->dualQuadSlots;
1117 
1118 #if (CY_IP_MXSMIF_VERSION>=2)
1119         if(cmdProg->cmdWidth == CY_SMIF_WIDTH_OCTAL)
1120         {
1121             /* The page program command */
1122             result = Cy_SMIF_TransmitCommand_Ext( base, (uint16_t)(cmdProg->command | cmdProg->command << 8),
1123                     true,
1124                     cmdProg->cmdWidth, cmdProg->cmdRate,
1125                     addr, device->numOfAddrBytes,
1126                     cmdProg->addrWidth, cmdProg->addrRate, slaveSelected, CY_SMIF_TX_NOT_LAST_BYTE,
1127                     context);
1128 
1129             if((CY_SMIF_SUCCESS == result) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdProg->mode))
1130             {
1131                 result = Cy_SMIF_TransmitCommand(base, (uint8_t)cmdProg->mode,
1132                             cmdProg->modeWidth, NULL,
1133                             CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
1134                             (cy_en_smif_slave_select_t)slaveSelected,
1135                             CY_SMIF_TX_NOT_LAST_BYTE, context);
1136             }
1137 
1138             if((CY_SMIF_SUCCESS == result) && (cmdProg->dummyCycles > 0U))
1139             {
1140                 result = Cy_SMIF_SendDummyCycles_Ext(base, CY_SMIF_WIDTH_OCTAL, cmdProg->addrRate, cmdProg->dummyCycles);
1141             }
1142 
1143             if(CY_SMIF_SUCCESS == result)
1144             {
1145                 result = Cy_SMIF_TransmitData_Ext( base, writeBuff, size,
1146                         cmdProg->dataWidth, cmdProg->dataRate, cmdCompleteCb, context);
1147             }
1148 
1149         }
1150         else
1151         {
1152 #endif
1153             /* The page program command */
1154             result = Cy_SMIF_TransmitCommand( base, (uint8_t)cmdProg->command,
1155                     cmdProg->cmdWidth, addr, device->numOfAddrBytes,
1156                     cmdProg->addrWidth, slaveSelected, CY_SMIF_TX_NOT_LAST_BYTE,
1157                     context);
1158 
1159             if((CY_SMIF_SUCCESS == result) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdProg->mode))
1160             {
1161                 result = Cy_SMIF_TransmitCommand(base, (uint8_t)cmdProg->mode,
1162                             cmdProg->modeWidth, NULL,
1163                             CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
1164                             (cy_en_smif_slave_select_t)slaveSelected,
1165                             CY_SMIF_TX_NOT_LAST_BYTE, context);
1166             }
1167 
1168             if((CY_SMIF_SUCCESS == result) && (cmdProg->dummyCycles > 0U))
1169             {
1170                 result = Cy_SMIF_SendDummyCycles(base, cmdProg->dummyCycles);
1171             }
1172 
1173             if(CY_SMIF_SUCCESS == result)
1174             {
1175                 result = Cy_SMIF_TransmitData( base, writeBuff, size,
1176                         cmdProg->dataWidth, cmdCompleteCb, context);
1177             }
1178 #if (CY_IP_MXSMIF_VERSION>=2)
1179         }
1180 #endif
1181     }
1182 
1183     return(result);
1184 }
1185 
1186 
1187 /*******************************************************************************
1188 * Function Name: Cy_SMIF_MemCmdRead
1189 ****************************************************************************//**
1190 *
1191 * This function performs the Read operation.
1192 *
1193 * \note This function uses the Cy_SMIF_TransmitCommand() API.
1194 * The Cy_SMIF_TransmitCommand() API works in the blocking mode. In the dual quad mode,
1195 * this API works with both types of memory simultaneously.
1196 *
1197 * \param base
1198 * Holds the base address of the SMIF block registers.
1199 *
1200 * \param memDevice
1201 * The device to which the command is sent.
1202 *
1203 * \param addr
1204 * The address to read.
1205 *
1206 * \param readBuff
1207 * The pointer to the variable where the read data is stored. If this pointer is
1208 * a NULL, then the function does not enable the interrupt. This use case is
1209 * typically used when the FIFO is handled outside the interrupt and is managed
1210 * in either a  polling-based code or a DMA. The user would handle the FIFO
1211 * management in a DMA or a polling-based code.
1212 * If the user provides a NULL pointer in this function and does not handle
1213 * the FIFO transaction, this could either stall or timeout the operation
1214 * \ref Cy_SMIF_TransmitData().
1215 *
1216 * \param size
1217 * The size of data to read.
1218 *
1219 * \param cmdCompleteCb
1220 * The callback function to call after the transfer completion. NULL interpreted
1221 * as no callback.
1222 *
1223 * \param context
1224 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1225 * allocated by the user. The structure is used during the SMIF
1226 * operation for internal configuration and data retention. The user must not
1227 * modify anything in this structure.
1228 *
1229 * \return A status of the transmission.
1230 *       - \ref CY_SMIF_SUCCESS
1231 *       - \ref CY_SMIF_CMD_FIFO_FULL
1232 *       - \ref CY_SMIF_BAD_PARAM
1233 *       - \ref CY_SMIF_EXCEED_TIMEOUT
1234 *       - \ref CY_SMIF_CMD_NOT_FOUND
1235 *
1236 * \note Check \ref group_smif_usage_rules for any usage restriction
1237 *
1238 *******************************************************************************/
Cy_SMIF_MemCmdRead(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,uint8_t const * addr,uint8_t * readBuff,uint32_t size,cy_smif_event_cb_t cmdCompleteCb,cy_stc_smif_context_t * context)1239 cy_en_smif_status_t Cy_SMIF_MemCmdRead(SMIF_Type *base,
1240                                 cy_stc_smif_mem_config_t const *memDevice,
1241                                 uint8_t const *addr,
1242                                 uint8_t* readBuff,
1243                                 uint32_t size,
1244                                 cy_smif_event_cb_t cmdCompleteCb,
1245                                 cy_stc_smif_context_t *context)
1246 {
1247     cy_en_smif_status_t result = CY_SMIF_BAD_PARAM;
1248     cy_en_smif_slave_select_t slaveSelected;
1249     cy_stc_smif_mem_device_cfg_t *device = memDevice->deviceCfg;
1250     cy_stc_smif_mem_cmd_t *cmdRead = device->readCmd;
1251 
1252     if(NULL == cmdRead)
1253     {
1254         result = CY_SMIF_CMD_NOT_FOUND;
1255     }
1256     else if(NULL == addr)
1257     {
1258         result = CY_SMIF_BAD_PARAM;
1259     }
1260     else
1261     {
1262         slaveSelected = (0U == memDevice->dualQuadSlots)?  memDevice->slaveSelect :
1263                                (cy_en_smif_slave_select_t)memDevice->dualQuadSlots;
1264 
1265         result = Cy_SMIF_TransmitCommand( base, (uint8_t)cmdRead->command,
1266                     cmdRead->cmdWidth, addr, device->numOfAddrBytes,
1267                     cmdRead->addrWidth, slaveSelected, CY_SMIF_TX_NOT_LAST_BYTE,
1268                     context);
1269 
1270         if((CY_SMIF_SUCCESS == result) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdRead->mode))
1271         {
1272             result = Cy_SMIF_TransmitCommand(base, (uint8_t)cmdRead->mode,
1273                         cmdRead->modeWidth, NULL,
1274                         CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
1275                         (cy_en_smif_slave_select_t)slaveSelected,
1276                         CY_SMIF_TX_NOT_LAST_BYTE, context);
1277         }
1278 
1279         if((CY_SMIF_SUCCESS == result) && (0U < cmdRead->dummyCycles))
1280         {
1281             result = Cy_SMIF_SendDummyCycles(base, cmdRead->dummyCycles);
1282         }
1283 
1284         if(CY_SMIF_SUCCESS == result)
1285         {
1286             result = Cy_SMIF_ReceiveData(base, readBuff, size,
1287                         cmdRead->dataWidth, cmdCompleteCb, context);
1288         }
1289     }
1290 
1291     return(result);
1292 }
1293 
1294 
1295 /*******************************************************************************
1296 * Function Name: Cy_SMIF_MemLocateHybridRegion
1297 ****************************************************************************//**
1298 *
1299 * This function locates the region structure by the address which belongs to it.
1300 *
1301 * \note This function is valid for the memories with hybrid sectors.
1302 *
1303 * \param memDevice
1304 * The memory device configuration.
1305 *
1306 * \param regionInfo
1307 * Places a hybrid region configuration structure that contains the region
1308 * specific parameters. See \ref cy_stc_smif_hybrid_region_info_t for
1309 * reference.
1310 *
1311 * \param address
1312 * The address for which a region is searched.
1313 *
1314 * \return A status of the region location.
1315 *       - \ref CY_SMIF_SUCCESS
1316 *       - \ref CY_SMIF_NOT_HYBRID_MEM
1317 *       - \ref CY_SMIF_BAD_PARAM
1318 *
1319 * \funcusage
1320 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemLocateHybridRegion
1321 *
1322 *******************************************************************************/
Cy_SMIF_MemLocateHybridRegion(cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_hybrid_region_info_t ** regionInfo,uint32_t address)1323 cy_en_smif_status_t Cy_SMIF_MemLocateHybridRegion(cy_stc_smif_mem_config_t const *memDevice,
1324                                                cy_stc_smif_hybrid_region_info_t** regionInfo,
1325                                                uint32_t address)
1326 {
1327     cy_en_smif_status_t result = CY_SMIF_BAD_PARAM;
1328     cy_stc_smif_hybrid_region_info_t* currInfo = NULL;
1329     CY_ASSERT_L1(NULL != memDevice);
1330     cy_stc_smif_mem_device_cfg_t *device = memDevice->deviceCfg;
1331 
1332     /* Check if the address exceeds the memory size */
1333     if(address < device->memSize)
1334     {
1335         result = CY_SMIF_NOT_HYBRID_MEM;
1336         /* Check if the memory is hybrid */
1337         if(NULL != device->hybridRegionInfo)
1338         {
1339             uint32_t idx;
1340             uint32_t regionStartAddr;
1341             uint32_t regionEndAddr;
1342             for(idx = 0UL; idx < device->hybridRegionCount; idx++)
1343             {
1344                 currInfo = device->hybridRegionInfo[idx];
1345                 regionStartAddr = currInfo->regionAddress;
1346                 regionEndAddr = regionStartAddr + (currInfo->sectorsCount * currInfo->eraseSize);
1347                 if ((address >= regionStartAddr) && (address < regionEndAddr))
1348                 {
1349                     *regionInfo = currInfo;
1350                     result = CY_SMIF_SUCCESS;
1351                     break;
1352                 }
1353             }
1354         }
1355     }
1356 
1357     return result;
1358 }
1359 
1360 /*******************************************************************************
1361 * Function Name: Cy_SMIF_SetReadyPollingDelay
1362 ****************************************************************************//**
1363 *
1364 * This function sets the polling delay in micro seconds to check memory device availability.
1365 * By default polling delay is set to 0.
1366 *
1367 * \param pollTimeoutUs
1368 * Specifies the polling timeout value in micro seconds.
1369 *
1370 * \param context
1371 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1372 * allocated by the user. The structure is used during the SMIF
1373 * operation for internal configuration and data retention. The user must not
1374 * modify anything in this structure.
1375 *
1376 *
1377 *******************************************************************************/
Cy_SMIF_SetReadyPollingDelay(uint16_t pollTimeoutUs,cy_stc_smif_context_t * context)1378 void Cy_SMIF_SetReadyPollingDelay(uint16_t pollTimeoutUs,
1379                                   cy_stc_smif_context_t *context)
1380 {
1381     CY_ASSERT_L1(NULL != context);
1382 
1383     context->memReadyPollDealy = pollTimeoutUs;
1384 }
1385 
1386 /*******************************************************************************
1387 * Function Name: Cy_SMIF_MemIsReady
1388 ****************************************************************************//**
1389 *
1390 * Polls the memory device to check whether it is ready to accept new commands or
1391 * not until either it is ready or the retries have exceeded the limit.
1392 * This is a blocking function, it will block the execution flow until
1393 * the command transmission is completed.
1394 *
1395 * \param base
1396 * Holds the base address of the SMIF block registers.
1397 *
1398 * \param memConfig
1399 * The memory device configuration.
1400 *
1401 * \param timeoutUs
1402 *  The timeout value in microseconds to apply while polling the memory.
1403 *
1404 * \param context
1405 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1406 * allocated by the user. The structure is used during the SMIF
1407 * operation for internal configuration and data retention. The user must not
1408 * modify anything in this structure.
1409 *
1410 * \return The status of the operation.
1411 * \ref CY_SMIF_SUCCESS        - Memory is ready to accept new commands.
1412 * \ref CY_SMIF_EXCEED_TIMEOUT - Memory is busy.
1413 *
1414 * \funcusage
1415 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemIsReady
1416 *
1417 *******************************************************************************/
Cy_SMIF_MemIsReady(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t timeoutUs,cy_stc_smif_context_t const * context)1418 cy_en_smif_status_t Cy_SMIF_MemIsReady(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1419                                        uint32_t timeoutUs, cy_stc_smif_context_t const *context)
1420 {
1421     bool isBusy = Cy_SMIF_Memslot_IsBusy(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1422 
1423     CY_ASSERT_L1(NULL != context);
1424 
1425     if (context->memReadyPollDealy > 0U)
1426     {
1427         if (isBusy)
1428         {
1429             uint16_t pollingDelay = (timeoutUs > context->memReadyPollDealy) ? context->memReadyPollDealy : (uint16_t)timeoutUs;
1430             do
1431             {
1432                 /* Avoid using weak function if XIP is enabled */
1433                 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1434                 {
1435                     Cy_SysLib_DelayUs(pollingDelay);
1436                 }
1437                 else
1438                 {
1439                     Cy_SysLib_Rtos_DelayUs(pollingDelay);
1440                 }
1441                 isBusy = Cy_SMIF_Memslot_IsBusy(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1442                 timeoutUs = (timeoutUs > pollingDelay) ? (timeoutUs - pollingDelay) : 0UL;
1443             } while(isBusy && (timeoutUs > 0UL));
1444         }
1445     }
1446     else
1447     {
1448         if(isBusy)
1449         {
1450             uint32_t delayMs = 0UL;
1451             uint32_t timeoutSlice = 0UL;
1452             uint16_t delayUs = 0U;
1453 
1454             /* Calculate the slice of time to split the timeoutUs delay into TIMEOUT_SLICE_DIV times */
1455             timeoutSlice = timeoutUs / TIMEOUT_SLICE_DIV;
1456 
1457             /* Reduce the slice if needed to avoid too big idle period between checking the busy state */
1458             if (timeoutSlice > TIMEOUT_SLICE_MAX)
1459             {
1460                 timeoutSlice = TIMEOUT_SLICE_MAX;
1461             }
1462             if(timeoutSlice == 0UL)
1463             {
1464                 timeoutSlice = 1UL;
1465             }
1466 
1467             do
1468             {
1469                 delayMs = timeoutSlice / 1000UL;
1470                 delayUs = (uint16_t) (timeoutSlice % 1000UL);
1471 
1472                 /* Avoid using weak function if XIP is enabled */
1473                 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1474                 {
1475                     Cy_SysLib_Delay(delayMs);
1476                     Cy_SysLib_DelayUs(delayUs);
1477                 }
1478                 else
1479                 {
1480                     Cy_SysLib_Rtos_Delay(delayMs);
1481                     Cy_SysLib_Rtos_DelayUs(delayUs);
1482                 }
1483 
1484                 isBusy = Cy_SMIF_Memslot_IsBusy(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1485 
1486                 timeoutUs = (timeoutUs > timeoutSlice) ? (timeoutUs - timeoutSlice) : 0UL;
1487 
1488             } while(isBusy && (timeoutUs > 0UL));
1489         }
1490     }
1491 
1492     return (isBusy ? CY_SMIF_EXCEED_TIMEOUT : CY_SMIF_SUCCESS);
1493 }
1494 
1495 
1496 /*******************************************************************************
1497 * Function Name: Cy_SMIF_MemIsQuadEnabled
1498 ****************************************************************************//**
1499 *
1500 * Checks whether the QE (Quad Enable) bit is set or not in the configuration
1501 * register of the memory.
1502 * This is a blocking function, it will block the execution flow until
1503 * the command transmission is completed.
1504 *
1505 * \param base
1506 * Holds the base address of the SMIF block registers.
1507 *
1508 * \param memConfig
1509 * The memory device configuration.
1510 *
1511 * \param isQuadEnabled
1512 * This parameter is updated to indicate whether quad mode is enabled (true) or
1513 * not (false). The value is valid only when the function returns
1514 * CY_SMIF_SUCCESS.
1515 *
1516 * \param context
1517 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1518 * allocated by the user. The structure is used during the SMIF
1519 * operation for internal configuration and data retention. The user must not
1520 * modify anything in this structure.
1521 *
1522 * \return The status of the operation. See \ref cy_en_smif_status_t.
1523 *
1524 * \funcusage
1525 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemIsQuadEnabled
1526 *
1527 *******************************************************************************/
Cy_SMIF_MemIsQuadEnabled(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,bool * isQuadEnabled,cy_stc_smif_context_t const * context)1528 cy_en_smif_status_t Cy_SMIF_MemIsQuadEnabled(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1529                                              bool *isQuadEnabled, cy_stc_smif_context_t const *context)
1530 {
1531     cy_en_smif_status_t status;
1532     uint8_t readStatus = 0U;
1533     CY_ASSERT_L1(NULL !=  memConfig);
1534     uint32_t statusCmd = memConfig->deviceCfg->readStsRegQeCmd->command;
1535     uint8_t maskQE = (uint8_t) memConfig->deviceCfg->stsRegQuadEnableMask;
1536 
1537     status = Cy_SMIF_MemCmdReadStatus(base, memConfig, &readStatus, (uint8_t)statusCmd, context);
1538 
1539     *isQuadEnabled = false;
1540     if(CY_SMIF_SUCCESS == status)
1541     {
1542         /* Check whether quad mode is already enabled or not */
1543         *isQuadEnabled = (maskQE == (readStatus & maskQE));
1544     }
1545 
1546     return status;
1547 }
1548 
1549 
1550 /*******************************************************************************
1551 * Function Name: Cy_SMIF_MemEnableQuadMode
1552 ****************************************************************************//**
1553 *
1554 * Sets the QE (QUAD Enable) bit in the external memory
1555 * configuration register to enable quad SPI mode.
1556 * This is a blocking function, it will block the execution flow until
1557 * the command transmission is completed.
1558 *
1559 * \param base
1560 * Holds the base address of the SMIF block registers.
1561 *
1562 * \param memConfig
1563 * The memory device configuration.
1564 *
1565 * \param timeoutUs
1566 *  The timeout value in microseconds to apply while polling the memory.
1567 *
1568 * \param context
1569 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1570 * allocated by the user. The structure is used during the SMIF
1571 * operation for internal configuration and data retention. The user must not
1572 * modify anything in this structure.
1573 *
1574 * \return The status of the operation. See \ref cy_en_smif_status_t.
1575 *
1576 * \funcusage
1577 * See \ref Cy_SMIF_MemIsQuadEnabled usage.
1578 *
1579 *******************************************************************************/
Cy_SMIF_MemEnableQuadMode(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t timeoutUs,cy_stc_smif_context_t const * context)1580 cy_en_smif_status_t Cy_SMIF_MemEnableQuadMode(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1581                                               uint32_t timeoutUs, cy_stc_smif_context_t const *context)
1582 {
1583     cy_en_smif_status_t status;
1584 
1585     CY_ASSERT_L1(NULL !=  memConfig);
1586 
1587     /* Send Write Enable to the external memory */
1588     status = Cy_SMIF_MemCmdWriteEnable(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1589 
1590     if(CY_SMIF_SUCCESS == status)
1591     {
1592         status = Cy_SMIF_MemQuadEnable(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1593 
1594         if(CY_SMIF_SUCCESS == status)
1595         {
1596             /* Poll the memory for the completion of the operation */
1597             status = Cy_SMIF_MemIsReady(base, memConfig, timeoutUs, context);
1598         }
1599     }
1600 
1601     return status;
1602 }
1603 
1604 /*******************************************************************************
1605 * Function Name: Cy_SMIF_MemRead
1606 ****************************************************************************//**
1607 *
1608 * Reads data from the external memory and blocks until the read
1609 * transfer is complete or a timeout occurs.
1610 * This is a blocking function, it will block the execution flow until
1611 * the command transmission is completed.
1612 *
1613 * \param base
1614 * Holds the base address of the SMIF block registers.
1615 *
1616 * \param memConfig
1617 * The memory device configuration.
1618 *
1619 * \param address
1620 * The address to read data from.
1621 *
1622 * \param rxBuffer
1623 * The buffer for storing the read data.
1624 *
1625 * \param length
1626 * The size of data to read.
1627 *
1628 * \param context
1629 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1630 * allocated by the user. The structure is used during the SMIF
1631 * operation for internal configuration and data retention. The user must not
1632 * modify anything in this structure.
1633 *
1634 * \return The status of the operation. See \ref cy_en_smif_status_t.
1635 *
1636 * \funcusage
1637 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemRead
1638 *
1639 *******************************************************************************/
Cy_SMIF_MemRead(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t address,uint8_t rxBuffer[],uint32_t length,cy_stc_smif_context_t const * context)1640 cy_en_smif_status_t Cy_SMIF_MemRead(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1641                                     uint32_t address, uint8_t rxBuffer[],
1642                                     uint32_t length, cy_stc_smif_context_t const *context)
1643 {
1644     cy_en_smif_status_t status = CY_SMIF_BAD_PARAM;
1645     uint32_t chunk = 0UL;
1646     uint8_t addrArray[CY_SMIF_FOUR_BYTES_ADDR] = {0U};
1647     cy_stc_smif_mem_cmd_t *cmdRead;
1648 
1649     CY_ASSERT_L1(NULL != memConfig);
1650     CY_ASSERT_L1(NULL != rxBuffer);
1651 
1652     cmdRead = memConfig->deviceCfg->readCmd;
1653 
1654     if((address + length) <= memConfig->deviceCfg->memSize)  /* Check if the address exceeds the memory size */
1655     {
1656         uint32_t interruptState = 0;
1657 
1658         /* If XIP is enabled, disable interrupts to avoid task switching to XIP location */
1659         if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1660         {
1661             interruptState = Cy_SysLib_EnterCriticalSection();
1662         }
1663 
1664         /* SMIF can read only up to 65536 bytes in one go. Split the larger read into multiple chunks */
1665         while (length > 0UL)
1666         {
1667             /* Get the number of bytes which can be read during one operation */
1668             chunk = (length > SMIF_MAX_RX_COUNT) ? (SMIF_MAX_RX_COUNT) : length;
1669             ValueToByteArray(address, &addrArray[0], 0UL,
1670                              memConfig->deviceCfg->numOfAddrBytes);
1671 
1672 #if (CY_IP_MXSMIF_VERSION>=2)
1673             status = Cy_SMIF_TransmitCommand_Ext(base,
1674                                              (uint16_t)(cmdRead->command | cmdRead->commandH << 8),
1675                                              ((bool)cmdRead->commandH),
1676                                              cmdRead->cmdWidth,
1677                                              cmdRead->cmdRate,
1678                                              (const uint8_t *)addrArray,
1679                                              memConfig->deviceCfg->numOfAddrBytes,
1680                                              cmdRead->addrWidth,
1681                                              cmdRead->addrRate,
1682                                              memConfig->slaveSelect,
1683                                              CY_SMIF_TX_NOT_LAST_BYTE,
1684                                              context);
1685 
1686             if((CY_SMIF_SUCCESS == status) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdRead->mode))
1687             {
1688                 status = Cy_SMIF_TransmitCommand_Ext(base,
1689                                                  (uint16_t)cmdRead->mode,
1690                                                  false,
1691                                                  cmdRead->modeWidth,
1692                                                  cmdRead->modeRate,
1693                                                  NULL,
1694                                                  CY_SMIF_CMD_WITHOUT_PARAM,
1695                                                  CY_SMIF_WIDTH_NA,
1696                                                  cmdRead->modeRate,
1697                                                  memConfig->slaveSelect,
1698                                                  CY_SMIF_TX_NOT_LAST_BYTE,
1699                                                  context);
1700             }
1701 
1702             if((CY_SMIF_SUCCESS == status) && (0U < cmdRead->dummyCycles))
1703             {
1704                 status = Cy_SMIF_SendDummyCycles_Ext(base, cmdRead->dataWidth, cmdRead->dataRate, cmdRead->dummyCycles);
1705             }
1706 
1707             if(CY_SMIF_SUCCESS == status)
1708             {
1709                  status = Cy_SMIF_ReceiveDataBlocking_Ext(base,
1710                                             rxBuffer,
1711                                             chunk,
1712                                             cmdRead->dataWidth,
1713                                             cmdRead->dataRate,
1714                                             context);
1715             }
1716 #else
1717             status = Cy_SMIF_TransmitCommand(base,
1718                                                 (uint8_t)cmdRead->command,
1719                                                 cmdRead->cmdWidth,
1720                                                 (const uint8_t *)addrArray,
1721                                                 memConfig->deviceCfg->numOfAddrBytes,
1722                                                 cmdRead->addrWidth,
1723                                                 memConfig->slaveSelect,
1724                                                 CY_SMIF_TX_NOT_LAST_BYTE,
1725                                                 context);
1726 
1727             if((CY_SMIF_SUCCESS == status) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdRead->mode))
1728             {
1729                 status = Cy_SMIF_TransmitCommand(base,
1730                                                     (uint8_t)cmdRead->mode,
1731                                                     cmdRead->modeWidth,
1732                                                     NULL,
1733                                                     CY_SMIF_CMD_WITHOUT_PARAM,
1734                                                     CY_SMIF_WIDTH_NA,
1735                                                     memConfig->slaveSelect,
1736                                                     CY_SMIF_TX_NOT_LAST_BYTE,
1737                                                     context);
1738             }
1739 
1740             if((CY_SMIF_SUCCESS == status) && (0U < cmdRead->dummyCycles))
1741             {
1742                 status = Cy_SMIF_SendDummyCycles(base, cmdRead->dummyCycles);
1743             }
1744 
1745             if(CY_SMIF_SUCCESS == status)
1746             {
1747                     status = Cy_SMIF_ReceiveDataBlocking(base,
1748                                             rxBuffer,
1749                                             chunk,
1750                                             cmdRead->dataWidth,
1751                                             context);
1752             }
1753 #endif /* CY_IP_MXSMIF_VERSION */
1754 
1755             if(CY_SMIF_SUCCESS != status)
1756             {
1757                 break;
1758             }
1759 
1760             /* Recalculate the next rxBuffer offset */
1761             length -= chunk;
1762             address += chunk;
1763             rxBuffer = (uint8_t *)rxBuffer + chunk;
1764         }
1765         /* Restore interrupts */
1766         if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1767         {
1768              Cy_SysLib_ExitCriticalSection(interruptState);
1769         }
1770     }
1771 
1772     return status;
1773 }
1774 
1775 
1776 /*******************************************************************************
1777 * Function Name: Cy_SMIF_MemWrite
1778 ****************************************************************************//**
1779 *
1780 * This function writes data to the external memory.
1781 * This is a blocking function, it will block the execution flow until
1782 * the command transmission is completed.
1783 *
1784 * \param base
1785 * Holds the base address of the SMIF block registers.
1786 *
1787 * \param memConfig
1788 * The memory device configuration.
1789 *
1790 * \param address
1791 * The address to write data at.
1792 *
1793 * \param txBuffer
1794 * The buffer holding the data to write in the external memory.
1795 *
1796 * \param length
1797 * The size of data to write.
1798 *
1799 * \param context
1800 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1801 * allocated by the user. The structure is used during the SMIF
1802 * operation for internal configuration and data retention. The user must not
1803 * modify anything in this structure.
1804 *
1805 * \return The status of the operation. See \ref cy_en_smif_status_t.
1806 *
1807 * \funcusage
1808 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemWrite
1809 *
1810 *******************************************************************************/
Cy_SMIF_MemWrite(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t address,uint8_t const txBuffer[],uint32_t length,cy_stc_smif_context_t const * context)1811 cy_en_smif_status_t Cy_SMIF_MemWrite(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1812                                      uint32_t address, uint8_t const txBuffer[],
1813                                      uint32_t length, cy_stc_smif_context_t const *context)
1814 {
1815     cy_en_smif_status_t status = CY_SMIF_BAD_PARAM;
1816     uint32_t offset = 0UL;
1817     uint32_t chunk = 0UL;
1818     uint32_t pageSize;
1819     uint8_t addrArray[CY_SMIF_FOUR_BYTES_ADDR] = {0U};
1820     cy_stc_smif_mem_cmd_t *cmdProgram;
1821 
1822     CY_ASSERT_L1(NULL != memConfig);
1823     CY_ASSERT_L1(NULL != txBuffer);
1824 
1825     pageSize = memConfig->deviceCfg->programSize; /* Get the page size */
1826     cmdProgram = memConfig->deviceCfg->programCmd; /* Get the program command */
1827 
1828     if((address + length) <= memConfig->deviceCfg->memSize)  /* Check if the address exceeds the memory size */
1829     {
1830         uint32_t interruptState = 0;
1831 
1832         /* If XIP is enabled, disable interrupts to avoid task switching to XIP location */
1833         if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1834         {
1835             interruptState = Cy_SysLib_EnterCriticalSection();
1836         }
1837         /* SMIF can read only up to 65536 bytes in one go. Split the larger read into multiple chunks */
1838         while (length > 0UL)
1839         {
1840             /* Get the number of bytes which can be written during one operation */
1841             offset = address % pageSize;
1842             chunk = ((offset + length) < pageSize) ? length : (pageSize - offset);
1843 
1844             /* The Write Enable bit may be cleared by the memory after every successful
1845              * operation of write or erase operations. Therefore, must be set for
1846              * every loop.
1847              */
1848             status = Cy_SMIF_MemCmdWriteEnable(base, memConfig, context);
1849 
1850             if(CY_SMIF_SUCCESS == status)
1851             {
1852                 ValueToByteArray(address, &addrArray[0], 0UL,
1853                                  memConfig->deviceCfg->numOfAddrBytes);
1854 #if (CY_IP_MXSMIF_VERSION>=2)
1855                 status = Cy_SMIF_TransmitCommand_Ext(base,
1856                                                 (uint16_t)(cmdProgram->command | cmdProgram->commandH << 8),
1857                                                 (bool)cmdProgram->commandH,
1858                                                 cmdProgram->cmdWidth, cmdProgram->cmdRate,
1859                                                 (const uint8_t *)addrArray, memConfig->deviceCfg->numOfAddrBytes,
1860                                                 cmdProgram->addrWidth, cmdProgram->addrRate,
1861                                                 memConfig->slaveSelect, CY_SMIF_TX_NOT_LAST_BYTE, context);
1862 
1863                 if((CY_SMIF_SUCCESS == status) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdProgram->mode))
1864                 {
1865                     status = Cy_SMIF_TransmitCommand_Ext(base,
1866                                                      (uint16_t)cmdProgram->mode, false,
1867                                                      cmdProgram->modeWidth, cmdProgram->modeRate,
1868                                                      NULL, CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
1869                                                      cmdProgram->modeRate, memConfig->slaveSelect,
1870                                                      CY_SMIF_TX_NOT_LAST_BYTE, context);
1871                 }
1872 
1873                 if((CY_SMIF_SUCCESS == status) && (cmdProgram->dummyCycles > 0U))
1874                 {
1875                     status = Cy_SMIF_SendDummyCycles_Ext(base, cmdProgram->dataWidth, cmdProgram->dataRate, cmdProgram->dummyCycles);
1876                 }
1877 
1878                 if(CY_SMIF_SUCCESS == status)
1879                 {
1880                     status = Cy_SMIF_TransmitDataBlocking_Ext(base,
1881                                                          (uint8_t *)txBuffer, chunk,
1882                                                          cmdProgram->dataWidth, cmdProgram->dataRate, context);
1883                 }
1884 #else
1885                 status = Cy_SMIF_TransmitCommand(base,
1886                                                  (uint8_t)cmdProgram->command,
1887                                                  cmdProgram->cmdWidth,
1888                                                  (const uint8_t *)addrArray,
1889                                                  memConfig->deviceCfg->numOfAddrBytes,
1890                                                  cmdProgram->addrWidth,
1891                                                  memConfig->slaveSelect,
1892                                                  CY_SMIF_TX_NOT_LAST_BYTE,
1893                                                  context);
1894 
1895                 if((CY_SMIF_SUCCESS == status) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdProgram->mode))
1896                 {
1897                     status = Cy_SMIF_TransmitCommand(base,
1898                                                      (uint8_t)cmdProgram->mode,
1899                                                      cmdProgram->modeWidth,
1900                                                      NULL,
1901                                                      CY_SMIF_CMD_WITHOUT_PARAM,
1902                                                      CY_SMIF_WIDTH_NA,
1903                                                      memConfig->slaveSelect,
1904                                                      CY_SMIF_TX_NOT_LAST_BYTE,
1905                                                      context);
1906                 }
1907 
1908                 if((CY_SMIF_SUCCESS == status) && (cmdProgram->dummyCycles > 0U))
1909                 {
1910                     status = Cy_SMIF_SendDummyCycles(base, cmdProgram->dummyCycles);
1911                 }
1912 
1913                 if(CY_SMIF_SUCCESS == status)
1914                 {
1915                     status = Cy_SMIF_TransmitDataBlocking(base,
1916                                                          (uint8_t *)txBuffer,
1917                                                          chunk,
1918                                                          cmdProgram->dataWidth,
1919                                                          context);
1920                 }
1921 #endif /* CY_IP_MXSMIF_VERSION */
1922                 if(CY_SMIF_SUCCESS == status)
1923                 {
1924                     /* Check if the memory has completed the write operation. ProgramTime is in microseconds */
1925                     status = Cy_SMIF_MemIsReady(base, memConfig, memConfig->deviceCfg->programTime, context);
1926                 }
1927                     }
1928 
1929             if(CY_SMIF_SUCCESS != status)
1930             {
1931                 break;
1932             }
1933 
1934             /* Recalculate the next rxBuffer offset */
1935             txBuffer = (uint8_t *)txBuffer + chunk;
1936             address += chunk;
1937             length -= chunk;
1938         }
1939         /* Restore interrupts */
1940         if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1941         {
1942             Cy_SysLib_ExitCriticalSection(interruptState);
1943         }
1944     }
1945 
1946     return status;
1947 }
1948 
1949 
1950 /*******************************************************************************
1951 * Function Name: Cy_SMIF_MemEraseSector
1952 ****************************************************************************//**
1953 *
1954 * Erases a block/sector of the external memory.
1955 * This is a blocking function, it will block the execution flow until
1956 * the command transmission is completed.
1957 *
1958 * \param base
1959 * Holds the base address of the SMIF block registers.
1960 *
1961 * \param memConfig
1962 * The memory device configuration.
1963 *
1964 * \param address
1965 * The address of the block to be erased. The address will be aligned to
1966 * the start address of the sector in which address is located.
1967 *
1968 * \param length
1969 * The length of data to erase. The length will be aligned to the sector
1970 * boundary where end address is located. If length exceeds memory size
1971 * API returns \ref CY_SMIF_BAD_PARAM without performing erase operation.
1972 *
1973 * \param context
1974 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1975 * allocated by the user. The structure is used during the SMIF
1976 * operation for internal configuration and data retention. The user must not
1977 * modify anything in this structure.
1978 *
1979 * \return The status of the operation. See \ref cy_en_smif_status_t.
1980 *
1981 * \note Memories like hybrid have sectors of different sizes. \n
1982 * Check the address and length parameters before calling this function.
1983 *
1984 * \funcusage
1985 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemEraseSector
1986 *
1987 *******************************************************************************/
Cy_SMIF_MemEraseSector(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t address,uint32_t length,cy_stc_smif_context_t const * context)1988 cy_en_smif_status_t Cy_SMIF_MemEraseSector(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1989                                            uint32_t address, uint32_t length,
1990                                            cy_stc_smif_context_t const *context)
1991 {
1992     cy_en_smif_status_t status = CY_SMIF_SUCCESS;
1993     uint32_t endAddress = address + length - 1UL;
1994     uint32_t hybridRegionEnd = 0UL;
1995     uint32_t hybridRegionStart = 0UL;
1996     uint8_t addrArray[CY_SMIF_FOUR_BYTES_ADDR] = {0U};
1997     cy_stc_smif_hybrid_region_info_t* hybrInfo = NULL;
1998     CY_ASSERT_L1(NULL != memConfig);
1999     cy_stc_smif_mem_device_cfg_t *device = memConfig->deviceCfg;
2000     uint32_t eraseSectorSize = device->eraseSize;
2001     uint32_t maxEraseTime = device->eraseTime;
2002 
2003     /* Check if the address exceeds the memory size */
2004     if (endAddress < device->memSize)
2005     {
2006         /* Align start address and end address to corresponding sector boundary */
2007         cy_stc_smif_hybrid_region_info_t* regionInfo = NULL;
2008 
2009         /* Check if it is a hybrid memory */
2010         status = Cy_SMIF_MemLocateHybridRegion(memConfig, &regionInfo, address);
2011 
2012         if ((CY_SMIF_SUCCESS == status) && (regionInfo != NULL)) /* Hybrid */
2013         {
2014             uint32_t offsetInRegion = address - regionInfo->regionAddress;
2015             uint32_t sectorOffsetInRegion = offsetInRegion / regionInfo->eraseSize;
2016 
2017             /* Align start address */
2018             address = regionInfo->regionAddress + (sectorOffsetInRegion * regionInfo->eraseSize);
2019 
2020             /* Last hybrid region in desired block */
2021             status = Cy_SMIF_MemLocateHybridRegion(memConfig, &regionInfo, endAddress);
2022             if (CY_SMIF_SUCCESS == status)
2023             {
2024                 offsetInRegion = endAddress - regionInfo->regionAddress + 1UL;
2025                 sectorOffsetInRegion  = offsetInRegion / regionInfo->eraseSize;
2026                 if (0UL != offsetInRegion % regionInfo->eraseSize)
2027                 {
2028                     sectorOffsetInRegion++;
2029                 }
2030                 /* Align end address */
2031                 endAddress = regionInfo->regionAddress + (sectorOffsetInRegion * regionInfo->eraseSize) - 1UL;
2032 
2033                 /* Update length according the aligned start address and end address */
2034                 length = endAddress - address + 1UL;
2035             }
2036         }
2037         else /* Not hybrid (unified) sectors layout */
2038         {
2039             /* If start address is somewhere at the middle of erase page, align it to the page start */
2040             if (0UL != (address % eraseSectorSize))
2041             {
2042                 address = eraseSectorSize * (address / eraseSectorSize);
2043             }
2044 
2045             /* If end address is somewhere at the middle of erase page, align it to the page end */
2046             if (0UL != ((endAddress + 1UL) % eraseSectorSize))
2047             {
2048                 endAddress = (eraseSectorSize * (endAddress + 1UL) / eraseSectorSize);
2049             }
2050             /* Update length according the aligned start address and end address */
2051             length = endAddress - address + 1UL;
2052 
2053             status = CY_SMIF_SUCCESS;
2054         }
2055 
2056         /* Check if the address exceeds the memory size */
2057         if (endAddress < device->memSize)
2058         {
2059             uint32_t interruptState = 0UL;
2060 
2061             /* If XIP is enabled, disable interrupts to avoid task switching to a code running in
2062              * XIP when erase operation is ongoing */
2063             if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
2064             {
2065                 interruptState = Cy_SysLib_EnterCriticalSection();
2066             }
2067 
2068             while(length > 0UL)
2069             {
2070                 /* In case of hybrid memory - update erase size and time for current region */
2071                 status = Cy_SMIF_MemLocateHybridRegion(memConfig, &hybrInfo, address);
2072                 if (CY_SMIF_SUCCESS == status)
2073                 {
2074                     maxEraseTime =  hybrInfo->eraseTime;
2075                     eraseSectorSize = hybrInfo->eraseSize;
2076                     hybridRegionStart = hybrInfo->regionAddress;
2077                     hybridRegionEnd = (hybrInfo->sectorsCount * eraseSectorSize) + hybridRegionStart - 1UL;
2078                     if(endAddress < hybridRegionEnd)
2079                     {
2080                         hybridRegionEnd = endAddress;
2081                     }
2082                 }
2083                 else
2084                 {
2085                     hybridRegionEnd = endAddress;
2086                 }
2087 
2088                 while (address < hybridRegionEnd)
2089                 {
2090                     /* The Write Enable bit may be cleared by the memory after every successful
2091                     * operation of write/erase operations. Therefore, it must be set for
2092                     * every loop.
2093                     */
2094                     status = Cy_SMIF_MemCmdWriteEnable(base, memConfig, context);
2095                     if(CY_SMIF_SUCCESS == status)
2096                     {
2097                         ValueToByteArray(address, &addrArray[0], 0UL, device->numOfAddrBytes);
2098 
2099                         /* Send the command to erase one sector */
2100                         status = Cy_SMIF_MemCmdSectorErase(base, (cy_stc_smif_mem_config_t* )memConfig,
2101                                                            (const uint8_t *)addrArray, context);
2102                         if(CY_SMIF_SUCCESS == status)
2103                         {
2104                             /* Wait until the erase operation is completed or a timeout occurs.
2105                              * Note: eraseTime is in milliseconds */
2106                             status = Cy_SMIF_MemIsReady(base, memConfig, (maxEraseTime * ONE_MILLI_IN_MICRO), context);
2107 
2108                             /* Recalculate the next sector address offset */
2109                             if(length > eraseSectorSize)
2110                             {
2111                                 address += eraseSectorSize;
2112                                 length -= eraseSectorSize;
2113                             }
2114                             else
2115                             {
2116                                 length = 0;
2117                                 break;
2118                             }
2119                         }
2120                     }
2121 
2122                     if(CY_SMIF_SUCCESS != status)
2123                     {
2124                         break;
2125                     }
2126                 }
2127             }
2128 
2129             /* Restore interrupts */
2130             if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
2131             {
2132                 Cy_SysLib_ExitCriticalSection(interruptState);
2133             }
2134         }
2135         else
2136         {
2137             /* Aligned end address exceeds memory size */
2138             status = CY_SMIF_BAD_PARAM;
2139         }
2140     }
2141     else
2142     {
2143         /* end address exceeds memory size */
2144         status = CY_SMIF_BAD_PARAM;
2145     }
2146 
2147     return status;
2148 }
2149 
2150 
2151 /*******************************************************************************
2152 * Function Name: Cy_SMIF_MemEraseChip
2153 ****************************************************************************//**
2154 *
2155 * Erases the entire chip of the external memory.
2156 * This is a blocking function, it will block the execution flow until
2157 * the command transmission is completed.
2158 *
2159 * \param base
2160 * Holds the base address of the SMIF block registers.
2161 *
2162 * \param memConfig
2163 * The memory device configuration.
2164 *
2165 * \param context
2166 * This is the pointer to the context structure \ref cy_stc_smif_context_t
2167 * allocated by the user. The structure is used during the SMIF
2168 * operation for internal configuration and data retention. The user must not
2169 * modify anything in this structure.
2170 *
2171 * \return The status of the operation. See \ref cy_en_smif_status_t.
2172 *
2173 * \funcusage
2174 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemEraseChip
2175 *
2176 *******************************************************************************/
Cy_SMIF_MemEraseChip(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,cy_stc_smif_context_t const * context)2177 cy_en_smif_status_t Cy_SMIF_MemEraseChip(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
2178                                          cy_stc_smif_context_t const *context)
2179 {
2180     cy_en_smif_status_t status;
2181 
2182     CY_ASSERT_L1(NULL != memConfig);
2183 
2184     /* The Write Enable bit may be cleared by the memory after every successful
2185     * operation of write/erase operations. Therefore, it must be set for
2186     * every loop
2187     */
2188     status = Cy_SMIF_MemCmdWriteEnable(base, memConfig, context);
2189 
2190     if(CY_SMIF_SUCCESS == status)
2191     {
2192         /* Send the command to erase the entire chip */
2193         status = Cy_SMIF_MemCmdChipErase(base, memConfig, context);
2194 
2195         if(CY_SMIF_SUCCESS == status)
2196         {
2197             /* Wait until the erase operation is completed or a timeout occurs. chipEraseTime is in milliseconds */
2198             status = Cy_SMIF_MemIsReady(base, memConfig,
2199                      (memConfig->deviceCfg->chipEraseTime * ONE_MILLI_IN_MICRO), context);
2200         }
2201     }
2202 
2203     return status;
2204 }
2205 
2206 /*******************************************************************************
2207 * Function Name: Cy_SMIF_MemCmdPowerDown
2208 ****************************************************************************//**
2209 *
2210 * This function sends a Power-down command to the selected memory device in
2211 * Single SPI mode. Please note that, once \ref Cy_SMIF_MemCmdPowerDown is issued, external
2212 * memory will not respond to any other command except \ref Cy_SMIF_MemCmdReleasePowerDown.
2213 *
2214 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
2215 * Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode
2216 * this API should be called for each memory.
2217 *
2218 * \param base
2219 * Holds the base address of the SMIF block registers.
2220 *
2221 * \param memDevice
2222 * The device to which the command is sent.
2223 *
2224 * \param context
2225 * This is the pointer to the context structure \ref cy_stc_smif_context_t
2226 * allocated by the user. The structure is used during the SMIF
2227 * operation for internal configuration and data retention. The user must not
2228 * modify anything in this structure.
2229 *
2230 * \return A status of the command transmission.
2231 *        - \ref CY_SMIF_SUCCESS
2232 *        - \ref CY_SMIF_EXCEED_TIMEOUT
2233 *
2234 * \snippet smif/snippet/main.c SMIF_API: PowerDown
2235 *******************************************************************************/
Cy_SMIF_MemCmdPowerDown(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)2236 cy_en_smif_status_t Cy_SMIF_MemCmdPowerDown(SMIF_Type *base,
2237                                     cy_stc_smif_mem_config_t const *memDevice,
2238                                     cy_stc_smif_context_t const *context)
2239 {
2240 
2241     cy_en_smif_status_t result;
2242 
2243     /* The memory Power-down command */
2244     result = Cy_SMIF_TransmitCommand( base, CY_SMIF_POWER_DOWN_CMD,
2245                                           CY_SMIF_WIDTH_SINGLE,
2246                                           NULL,
2247                                           CY_SMIF_CMD_WITHOUT_PARAM,
2248                                           CY_SMIF_WIDTH_NA,
2249                                           memDevice->slaveSelect,
2250                                           CY_SMIF_TX_LAST_BYTE,
2251                                           context);
2252 
2253     return result;
2254 }
2255 /*******************************************************************************
2256 * Function Name: Cy_SMIF_MemCmdReleasePowerDown
2257 ****************************************************************************//**
2258 *
2259 * This function sends a Release Power-down command to the selected memory device
2260 * in Single SPI mode.
2261 *
2262 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
2263 * Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode
2264 * this API should be called for each memory.
2265 *
2266 * \param base
2267 * Holds the base address of the SMIF block registers.
2268 *
2269 * \param memDevice
2270 * The device to which the command is sent.
2271 *
2272 * \param context
2273 * This is the pointer to the context structure \ref cy_stc_smif_context_t
2274 * allocated by the user. The structure is used during the SMIF
2275 * operation for internal configuration and data retention. The user must not
2276 * modify anything in this structure.
2277 *
2278 * \return A status of the command transmission.
2279 *        - \ref CY_SMIF_SUCCESS
2280 *        - \ref CY_SMIF_EXCEED_TIMEOUT
2281 *
2282 * \snippet smif/snippet/main.c SMIF_API: PowerDown
2283 *******************************************************************************/
Cy_SMIF_MemCmdReleasePowerDown(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)2284 cy_en_smif_status_t Cy_SMIF_MemCmdReleasePowerDown(SMIF_Type *base,
2285                                     cy_stc_smif_mem_config_t const *memDevice,
2286                                     cy_stc_smif_context_t const *context)
2287 {
2288 
2289     cy_en_smif_status_t result;
2290 
2291     /* The memory Release Power-down command */
2292     result = Cy_SMIF_TransmitCommand( base, CY_SMIF_RELEASE_POWER_DOWN_CMD,
2293                                           CY_SMIF_WIDTH_SINGLE,
2294                                           NULL,
2295                                           CY_SMIF_CMD_WITHOUT_PARAM,
2296                                           CY_SMIF_WIDTH_NA,
2297                                           memDevice->slaveSelect,
2298                                           CY_SMIF_TX_LAST_BYTE,
2299                                           context);
2300 
2301     return result;
2302 }
2303 
2304 #if defined(__cplusplus)
2305 }
2306 #endif
2307 
2308 #endif /* CY_IP_MXSMIF */
2309 
2310 /* [] END OF FILE */
2311