1 /***************************************************************************//**
2 * \file cybsp_smif_init.c
3 *
4 * Description:
5 * Provides initialization code for SMIF.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 *     http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26 #if CY_PDL_FLASH_BOOT
27 #include "cybsp_smif_init.h"
28 #include "cycfg_pins.h"
29 #include "cyhal_pin_package.h"
30 
31 cy_stc_smif_context_t cybsp_smif_context;
32 
33 static uint32_t SMIF_PORT_SEL0;
34 static uint32_t SMIF_PORT_SEL1;
35 static uint32_t SMIF_CFG;
36 static uint32_t SMIF_OUT;
37 
38 /*******************************************************************************
39 * Function Name: smif_disable
40 ****************************************************************************//**
41 *
42 * it disable the the SMIF.
43 *
44 * \return NULL.
45 *
46 *******************************************************************************/
47 CY_RAMFUNC_BEGIN
cybsp_smif_disable()48 void cybsp_smif_disable()
49 {
50     // to minimize DeepSleep latency this code assumes that all of the SMIF pins are on the same
51     // port
52     int port_number= CYHAL_GET_PORT(CYBSP_QSPI_SS);
53     SMIF0->CTL = SMIF0->CTL & ~SMIF_CTL_ENABLED_Msk;
54     SMIF_PORT_SEL0 = ((HSIOM_PRT_Type*)&HSIOM->PRT[port_number])->PORT_SEL0;
55     SMIF_PORT_SEL1 = ((HSIOM_PRT_Type*)&HSIOM->PRT[port_number])->PORT_SEL1;
56     SMIF_CFG = ((GPIO_PRT_Type*)&GPIO->PRT[port_number])->CFG;
57     SMIF_OUT = ((GPIO_PRT_Type*)&GPIO->PRT[port_number])->OUT;
58     ((HSIOM_PRT_Type*)&HSIOM->PRT[port_number])->PORT_SEL0 = 0x00;
59     ((HSIOM_PRT_Type*)&HSIOM->PRT[port_number])->PORT_SEL1 = 0x00;
60     ((GPIO_PRT_Type*)&GPIO->PRT[port_number])->CFG = 0x600006;
61     ((GPIO_PRT_Type*)&GPIO->PRT[port_number])->OUT = 0x1;
62 }
63 
64 
65 CY_RAMFUNC_END
66 
67 /*******************************************************************************
68 * Function Name: smif_enable
69 ****************************************************************************//**
70 *
71 * it enable the the SMIF.
72 *
73 * \return NULL.
74 *
75 *******************************************************************************/
76 CY_RAMFUNC_BEGIN
cybsp_smif_enable()77 void cybsp_smif_enable()
78 {
79     int port_number= CYHAL_GET_PORT(CYBSP_QSPI_SS);
80     SMIF0->CTL = SMIF0->CTL | SMIF_CTL_ENABLED_Msk;
81     ((HSIOM_PRT_Type*)&HSIOM->PRT[port_number])->PORT_SEL0 = SMIF_PORT_SEL0;
82     ((HSIOM_PRT_Type*)&HSIOM->PRT[port_number])->PORT_SEL1 = SMIF_PORT_SEL1;
83     ((GPIO_PRT_Type*)&GPIO->PRT[port_number])->CFG = SMIF_CFG;
84     ((GPIO_PRT_Type*)&GPIO->PRT[port_number])->OUT = SMIF_OUT;
85 }
86 
87 
88 CY_RAMFUNC_END
89 
90 /*******************************************************************************
91 * Function Name: cybsp_is_memory_ready
92 ****************************************************************************//**
93 *
94 * Polls the memory device to check whether it is ready to accept new commands or
95 * not until either it is ready or the retries have exceeded the limit.
96 *
97 * \param memConfig
98 * memory device configuration
99 *
100 * \return Status of the operation.
101 * CY_SMIF_SUCCESS          - Memory is ready to accept new commands.
102 * CY_SMIF_EXCEED_TIMEOUT - Memory is busy.
103 *
104 *******************************************************************************/
105 #if defined (__ICCARM__)
106 /* Suppress warnings originating from configurator */
107 /* Ta022 : "Call to a non __ramfunc function from within a __ramfunc function"  */
108 CY_PRAGMA(diag_suppress = Ta022)
109 #endif
110 //--------------------------------------------------------------------------------------------------
111 // cybsp_is_memory_ready
112 //--------------------------------------------------------------------------------------------------
113 CY_RAMFUNC_BEGIN
114 
cybsp_is_memory_ready(cy_stc_smif_mem_config_t const * memConfig)115 cy_en_smif_status_t cybsp_is_memory_ready(cy_stc_smif_mem_config_t const* memConfig)
116 {
117     uint32_t retries = 0;
118     bool isBusy;
119 
120     do
121     {
122         isBusy =
123             Cy_SMIF_Memslot_IsBusy(SMIF_HW, (cy_stc_smif_mem_config_t*)memConfig,
124                                    &cybsp_smif_context);
125         Cy_SysLib_DelayUs(15);
126         retries++;
127     } while(isBusy && (retries < MEMORY_BUSY_CHECK_RETRIES));
128 
129     return (isBusy ? CY_SMIF_EXCEED_TIMEOUT : CY_SMIF_SUCCESS);
130 }
131 
132 
133 CY_RAMFUNC_END
134 #if defined (__ICCARM__)
135 CY_PRAGMA(diag_default = Ta022)
136 #endif
137 
138 /*******************************************************************************
139 * Function Name: cybsp_enable_quad_mode
140 ****************************************************************************//*
141 *
142 * This function sets the QE (QUAD Enable) bit in the external memory
143 * configuration register to enable Quad SPI mode.
144 *
145 * \param memConfig
146 * Memory device configuration
147 *
148 * \return Status of the operation. See cy_en_smif_status_t.
149 *
150 *******************************************************************************/
151 #if defined (__ICCARM__)
152 /* Suppress warnings originating from configurator */
153 /* Ta022 : "Call to a non __ramfunc function from within a __ramfunc function"  */
154 CY_PRAGMA(diag_suppress = Ta022)
155 #endif
156 //--------------------------------------------------------------------------------------------------
157 // cybsp_enable_quad_mode
158 //--------------------------------------------------------------------------------------------------
159 CY_RAMFUNC_BEGIN
160 
cybsp_enable_quad_mode(cy_stc_smif_mem_config_t const * memConfig)161 cy_en_smif_status_t cybsp_enable_quad_mode(cy_stc_smif_mem_config_t const* memConfig)
162 {
163     cy_en_smif_status_t status;
164 
165     /* Send Write Enable to external memory */
166     status = Cy_SMIF_Memslot_CmdWriteEnable(SMIF_HW, smifMemConfigs[0], &cybsp_smif_context);
167 
168     if (CY_SMIF_SUCCESS == status)
169     {
170         status = Cy_SMIF_Memslot_QuadEnable(SMIF_HW, (cy_stc_smif_mem_config_t*)memConfig,
171                                             &cybsp_smif_context);
172 
173         if (CY_SMIF_SUCCESS == status)
174         {
175             /* Poll memory for the completion of operation */
176             status = cybsp_is_memory_ready(memConfig);
177         }
178     }
179 
180     return status;
181 }
182 
183 
184 CY_RAMFUNC_END
185 #if defined (__ICCARM__)
186 CY_PRAGMA(diag_default = Ta022)
187 #endif
188 
189 
190 /*******************************************************************************
191 * Function Name: cybsp_is_quad_enabled
192 ****************************************************************************//**
193 *
194 * Checks whether QE (Quad Enable) bit is set or not in the configuration
195 * register of the memory.
196 *
197 * \param memConfig
198 * Memory device configuration
199 *
200 * \param isQuadEnabled
201 * This parameter is updated to indicate whether Quad mode is enabled (true) or
202 * not (false). The value is valid only when the function returns
203 * CY_SMIF_SUCCESS.
204 *
205 * \return Status of the operation. See cy_en_smif_status_t.
206 *
207 *******************************************************************************/
208 #if defined (__ICCARM__)
209 /* Suppress warnings originating from configurator */
210 /* Ta022 : "Call to a non __ramfunc function from within a __ramfunc function"  */
211 CY_PRAGMA(diag_suppress = Ta022)
212 #endif
213 //--------------------------------------------------------------------------------------------------
214 // cybsp_is_quad_enabled
215 //--------------------------------------------------------------------------------------------------
216 CY_RAMFUNC_BEGIN
217 
cybsp_is_quad_enabled(cy_stc_smif_mem_config_t const * memConfig,bool * isQuadEnabled)218 cy_en_smif_status_t cybsp_is_quad_enabled(cy_stc_smif_mem_config_t const* memConfig,
219                                           bool* isQuadEnabled)
220 {
221     cy_en_smif_status_t status;
222     uint8_t readStatus = 0;
223     uint32_t statusCmd = memConfig->deviceCfg->readStsRegQeCmd->command;
224     uint8_t maskQE = (uint8_t)memConfig->deviceCfg->stsRegQuadEnableMask;
225 
226     status = Cy_SMIF_Memslot_CmdReadSts(SMIF_HW, memConfig, &readStatus, statusCmd,
227                                         &cybsp_smif_context);
228 
229     *isQuadEnabled = false;
230     if (CY_SMIF_SUCCESS == status)
231     {
232         /* Check whether Quad mode is already enabled or not */
233         *isQuadEnabled = (maskQE == (readStatus & maskQE));
234     }
235 
236     return status;
237 }
238 
239 
240 CY_RAMFUNC_END
241 #if defined (__ICCARM__)
242 CY_PRAGMA(diag_default = Ta022)
243 #endif
244 
245 
246 cy_stc_smif_config_t cybsp_smif_config =
247 {
248     .mode          = (uint32_t)CY_SMIF_NORMAL,
249     .deselectDelay = 7,
250     .rxClockSel    = (uint32_t)CY_SMIF_SEL_INVERTED_FEEDBACK_CLK,
251     .blockEvent    = (uint32_t)CY_SMIF_BUS_ERROR,
252 };
253 
254 /********************************************************
255 * cybsp_smif_start
256 *********************************************************
257 * Initializes the SMIF hardware, sets the slave select
258 * and enables the SMIF block.
259 *
260 * returns: the status of the block during initialization
261 *
262 ********************************************************/
263 #if defined (__ICCARM__)
264 /* Suppress warnings originating from configurator */
265 /* Ta022 : "Call to a non __ramfunc function from within a __ramfunc function"  */
266 CY_PRAGMA(diag_suppress = Ta022)
267 #endif
268 //--------------------------------------------------------------------------------------------------
269 // cybsp_smif_start
270 //--------------------------------------------------------------------------------------------------
271 CY_RAMFUNC_BEGIN
272 
cybsp_smif_start(void)273 cy_en_smif_status_t cybsp_smif_start(void)
274 {
275     cy_en_smif_status_t cybsp_smif_status = CY_SMIF_BAD_PARAM;
276 
277     cybsp_smif_status =
278         Cy_SMIF_Init(SMIF_HW, &cybsp_smif_config, TIMEOUT_1_MS, &cybsp_smif_context);
279 
280     if (cybsp_smif_status == CY_SMIF_SUCCESS)
281     {
282         Cy_SMIF_SetDataSelect(SMIF_HW, smifMemConfigs[0]->slaveSelect,
283                               smifMemConfigs[0]->dataSelect);
284         Cy_SMIF_Enable(SMIF_HW, &cybsp_smif_context);
285     }
286 
287     return cybsp_smif_status;
288 }
289 
290 
291 CY_RAMFUNC_END
292 #if defined (__ICCARM__)
293 CY_PRAGMA(diag_default = Ta022)
294 #endif
295 
296 
297 /********************************************************
298 * cybsp_smif_init
299 *********************************************************
300 * Configures the SMIF hardware
301 ********************************************************/
302 #if defined (__ICCARM__)
303 /* Suppress warnings originating from configurator */
304 /* Ta022 : "Call to a non __ramfunc function from within a __ramfunc function"  */
305 CY_PRAGMA(diag_suppress = Ta022)
306 #endif
307 //--------------------------------------------------------------------------------------------------
308 // cybsp_smif_init
309 //--------------------------------------------------------------------------------------------------
310 CY_RAMFUNC_BEGIN
311 
cybsp_smif_init(void)312 cy_en_smif_status_t cybsp_smif_init(void)
313 {
314     /* Initalization Status Holders */
315     cy_en_smif_status_t cybsp_smif_status = CY_SMIF_BAD_PARAM;
316     bool QE_status = false;
317 
318     cybsp_smif_status = cybsp_smif_start();
319 
320     if (cybsp_smif_status == CY_SMIF_SUCCESS)
321     {
322         cybsp_smif_status = Cy_SMIF_MemCmdReleasePowerDown(SMIF0,
323                                                            smifMemConfigs[0],
324                                                            &cybsp_smif_context);
325 
326         if (CY_SMIF_SUCCESS == cybsp_smif_status)
327         {
328             cybsp_smif_status = cybsp_is_memory_ready(smifMemConfigs[0]);
329             if (CY_SMIF_SUCCESS == cybsp_smif_status)
330             {
331                 /* Map memory device to memory map */
332                 cybsp_smif_status = Cy_SMIF_Memslot_Init(SMIF_HW,
333                                                          (cy_stc_smif_block_config_t*)&smifBlockConfig,
334                                                          &cybsp_smif_context);
335                 if (cybsp_smif_status == CY_SMIF_SUCCESS)
336                 {
337                     /* Even after SFDP enumeration QE command is not initialised */
338                     /* So, it should be 1.0 device */
339                     if ((smifMemConfigs[0]->deviceCfg->readStsRegQeCmd->command ==
340                          CY_SMIF_NO_COMMAND_OR_MODE) ||
341                         (smifMemConfigs[0]->deviceCfg->readStsRegQeCmd->command == 0))
342                     {
343                         cybsp_smif_status = Cy_SMIF_MemInitSfdpMode(SMIF_HW,
344                                                                     smifMemConfigs[0],
345                                                                     CY_SMIF_WIDTH_QUAD,
346                                                                     CY_SMIF_SFDP_QER_1,
347                                                                     &cybsp_smif_context);
348                     }
349 
350                     if (cybsp_smif_status == CY_SMIF_SUCCESS)
351                     {
352                         /* Check if Quad mode is already enabled */
353                         cybsp_is_quad_enabled(smifMemConfigs[0], &QE_status);
354 
355                         /* If not enabled, enable quad mode */
356                         if (!QE_status)
357                         {
358                             /* Enable Quad mode */
359                             cybsp_smif_status = cybsp_enable_quad_mode(smifMemConfigs[0]);
360                         }
361                         if (cybsp_smif_status == CY_SMIF_SUCCESS)
362                         {
363                             /* Put the device in XIP mode */
364                             Cy_SMIF_SetMode(SMIF_HW, CY_SMIF_MEMORY);
365                         }
366                     }
367                 }
368             }
369         }
370     }
371 
372     return cybsp_smif_status;
373 }
374 
375 
376 CY_RAMFUNC_END
377 #if defined (__ICCARM__)
378 CY_PRAGMA(diag_default = Ta022)
379 #endif
380 
381 #endif // if CY_PDL_FLASH_BOOT
382