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