1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 /***************************************************************************//**
20 * \file flash_qspi.c
21 * \version 1.0
22 *
23 * \brief
24 * This is the source file of external flash driver adaptation layer between PSoC6
25 * and standard MCUBoot code.
26 *
27 ********************************************************************************
28 * \copyright
29 *
30 * (c) 2020, Cypress Semiconductor Corporation
31 * or a subsidiary of Cypress Semiconductor Corporation. All rights
32 * reserved.
33 *
34 * This software, including source code, documentation and related
35 * materials ("Software"), is owned by Cypress Semiconductor
36 * Corporation or one of its subsidiaries ("Cypress") and is protected by
37 * and subject to worldwide patent protection (United States and foreign),
38 * United States copyright laws and international treaty provisions.
39 * Therefore, you may use this Software only as provided in the license
40 * agreement accompanying the software package from which you
41 * obtained this Software ("EULA").
42 *
43 * If no EULA applies, Cypress hereby grants you a personal, non-
44 * exclusive, non-transferable license to copy, modify, and compile the
45 * Software source code solely for use in connection with Cypress?s
46 * integrated circuit products. Any reproduction, modification, translation,
47 * compilation, or representation of this Software except as specified
48 * above is prohibited without the express written permission of Cypress.
49 *
50 * Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
51 * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
52 * BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
53 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
54 * PARTICULAR PURPOSE. Cypress reserves the right to make
55 * changes to the Software without notice. Cypress does not assume any
56 * liability arising out of the application or use of the Software or any
57 * product or circuit described in the Software. Cypress does not
58 * authorize its products for use in any products where a malfunction or
59 * failure of the Cypress product may reasonably be expected to result in
60 * significant property damage, injury or death ("High Risk Product"). By
61 * including Cypress's product in a High Risk Product, the manufacturer
62 * of such system or application assumes all risk of such use and in doing
63 * so agrees to indemnify Cypress against all liability.
64 *
65 ******************************************************************************/
66 #include "cy_pdl.h"
67 #include <stdio.h>
68 #include "flash_qspi.h"
69
70 #define CY_SMIF_SYSCLK_HFCLK_DIVIDER CY_SYSCLK_CLKHF_DIVIDE_BY_4
71
72 /* This is the board specific stuff that should align with your board.
73 *
74 * QSPI resources:
75 *
76 * SS0 - P11_2
77 * SS1 - P11_1
78 * SS2 - P11_0
79 * SS3 - P12_4
80 *
81 * D3 - P11_3
82 * D2 - P11_4
83 * D1 - P11_5
84 * D0 - P11_6
85 *
86 * SCK - P11_7
87 *
88 * SMIF Block - SMIF0
89 *
90 */
91
92 /* SMIF SlaveSelect Configurations */
93 struct qspi_ss_config
94 {
95 GPIO_PRT_Type* SS_Port;
96 int SS_Pin;
97 en_hsiom_sel_t SS_Mux;
98 };
99
100 #if (defined(PSOC_064_2M) || \
101 defined(PSOC_064_1M) || \
102 defined(PSOC_062_2M) || \
103 defined(PSOC_062_1M))
104 #define CY_BOOTLOADER_SMIF_SS_CFG_NUM 4
105 #elif defined(PSOC_064_512K) || defined(PSOC_062_512K)
106 #define CY_BOOTLOADER_SMIF_SS_CFG_NUM 3
107 #else
108 #error "Platform device name is unsupported."
109 #endif
110 struct qspi_ss_config qspi_SS_Configuration[CY_BOOTLOADER_SMIF_SS_CFG_NUM] =
111 {
112 {
113 .SS_Port = GPIO_PRT11,
114 .SS_Pin = 2,
115 .SS_Mux = P11_2_SMIF_SPI_SELECT0
116 },
117 {
118 .SS_Port = GPIO_PRT11,
119 .SS_Pin = 1,
120 .SS_Mux = P11_1_SMIF_SPI_SELECT1
121 },
122 {
123 .SS_Port = GPIO_PRT11,
124 .SS_Pin = 0,
125 .SS_Mux = P11_0_SMIF_SPI_SELECT2
126 },
127 #if(CY_BOOTLOADER_SMIF_SS_CFG_NUM > 3)
128 {
129 .SS_Port = GPIO_PRT12,
130 .SS_Pin = 4,
131 .SS_Mux = P12_4_SMIF_SPI_SELECT3
132 }
133 #endif
134 };
135
136 static GPIO_PRT_Type *D3Port = GPIO_PRT11;
137 static int D3Pin = 3;
138 static en_hsiom_sel_t D3MuxPort = P11_3_SMIF_SPI_DATA3;
139
140 static GPIO_PRT_Type *D2Port = GPIO_PRT11;
141 static int D2Pin = 4;
142 static en_hsiom_sel_t D2MuxPort = P11_4_SMIF_SPI_DATA2;
143
144 static GPIO_PRT_Type *D1Port = GPIO_PRT11;
145 static int D1Pin = 5;
146 static en_hsiom_sel_t D1MuxPort = P11_5_SMIF_SPI_DATA1;
147
148 static GPIO_PRT_Type *D0Port = GPIO_PRT11;
149 static int D0Pin = 6;
150 static en_hsiom_sel_t D0MuxPort = P11_6_SMIF_SPI_DATA0;
151
152 static GPIO_PRT_Type *SCKPort = GPIO_PRT11;
153 static int SCKPin = 7;
154 static en_hsiom_sel_t SCKMuxPort = P11_7_SMIF_SPI_CLK;
155
156 static SMIF_Type *QSPIPort = SMIF0;
157
158 cy_stc_smif_mem_cmd_t sfdpcmd =
159 {
160 .command = 0x5A,
161 .cmdWidth = CY_SMIF_WIDTH_SINGLE,
162 .addrWidth = CY_SMIF_WIDTH_SINGLE,
163 .mode = 0xFFFFFFFFU,
164 .dummyCycles = 8,
165 .dataWidth = CY_SMIF_WIDTH_SINGLE,
166 };
167
168 static cy_stc_smif_mem_cmd_t rdcmd0;
169 static cy_stc_smif_mem_cmd_t wrencmd0;
170 static cy_stc_smif_mem_cmd_t wrdiscmd0;
171 static cy_stc_smif_mem_cmd_t erasecmd0;
172 static cy_stc_smif_mem_cmd_t chiperasecmd0;
173 static cy_stc_smif_mem_cmd_t pgmcmd0;
174 static cy_stc_smif_mem_cmd_t readsts0;
175 static cy_stc_smif_mem_cmd_t readstsqecmd0;
176 static cy_stc_smif_mem_cmd_t writestseqcmd0;
177
178 static cy_stc_smif_mem_device_cfg_t dev_sfdp_0 =
179 {
180 .numOfAddrBytes = 4,
181 .readSfdpCmd = &sfdpcmd,
182 .readCmd = &rdcmd0,
183 .writeEnCmd = &wrencmd0,
184 .writeDisCmd = &wrdiscmd0,
185 .programCmd = &pgmcmd0,
186 .eraseCmd = &erasecmd0,
187 .chipEraseCmd = &chiperasecmd0,
188 .readStsRegWipCmd = &readsts0,
189 .readStsRegQeCmd = &readstsqecmd0,
190 .writeStsRegQeCmd = &writestseqcmd0,
191 };
192
193 static cy_stc_smif_mem_config_t mem_sfdp_0 =
194 {
195 /* The base address the memory slave is mapped to in the PSoC memory map.
196 Valid when the memory-mapped mode is enabled. */
197 .baseAddress = 0x18000000U,
198 /* The size allocated in the PSoC memory map, for the memory slave device.
199 The size is allocated from the base address. Valid when the memory mapped mode is enabled. */
200 /* .memMappedSize = 0x4000000U, */
201 .flags = CY_SMIF_FLAG_DETECT_SFDP,
202 .slaveSelect = CY_SMIF_SLAVE_SELECT_0,
203 .dataSelect = CY_SMIF_DATA_SEL0,
204 .deviceCfg = &dev_sfdp_0
205 };
206
207 cy_stc_smif_mem_config_t *mems_sfdp[1] =
208 {
209 &mem_sfdp_0
210 };
211
212 /* make it exported if used in TOC (cy_serial_flash_prog.c) */
213 /* cy_stc_smif_block_config_t smifBlockConfig_sfdp = */
214 static cy_stc_smif_block_config_t smifBlockConfig_sfdp =
215 {
216 .memCount = 1,
217 .memConfig = mems_sfdp,
218 };
219
220 static cy_stc_smif_block_config_t *smif_blk_config;
221
222 static cy_stc_smif_context_t QSPI_context;
223
224 cy_stc_smif_config_t const QSPI_config =
225 {
226 .mode = CY_SMIF_NORMAL,
227 .deselectDelay = 1,
228 .rxClockSel = CY_SMIF_SEL_INV_INTERNAL_CLK,
229 .blockEvent = CY_SMIF_BUS_ERROR
230 };
231
232 cy_stc_sysint_t smifIntConfig =
233 {/* ATTENTION: make sure proper Interrupts configured for CM0p or M4 cores */
234 .intrSrc = NvicMux7_IRQn,
235 .cm0pSrc = smif_interrupt_IRQn,
236 .intrPriority = 1
237 };
238
239 /* SMIF pinouts configurations */
240 static cy_stc_gpio_pin_config_t QSPI_SS_config =
241 {
242 .outVal = 1,
243 .driveMode = CY_GPIO_DM_STRONG_IN_OFF,
244 .hsiom = P11_2_SMIF_SPI_SELECT0, /* lets use SS0 by default */
245 .intEdge = CY_GPIO_INTR_DISABLE,
246 .intMask = 0UL,
247 .vtrip = CY_GPIO_VTRIP_CMOS,
248 .slewRate = CY_GPIO_SLEW_FAST,
249 .driveSel = CY_GPIO_DRIVE_1_2,
250 .vregEn = 0UL,
251 .ibufMode = 0UL,
252 .vtripSel = 0UL,
253 .vrefSel = 0UL,
254 .vohSel = 0UL,
255 };
256 const cy_stc_gpio_pin_config_t QSPI_DATA3_config =
257 {
258 .outVal = 1,
259 .driveMode = CY_GPIO_DM_STRONG,
260 .hsiom = P11_3_SMIF_SPI_DATA3,
261 .intEdge = CY_GPIO_INTR_DISABLE,
262 .intMask = 0UL,
263 .vtrip = CY_GPIO_VTRIP_CMOS,
264 .slewRate = CY_GPIO_SLEW_FAST,
265 .driveSel = CY_GPIO_DRIVE_1_2,
266 .vregEn = 0UL,
267 .ibufMode = 0UL,
268 .vtripSel = 0UL,
269 .vrefSel = 0UL,
270 .vohSel = 0UL,
271 };
272 const cy_stc_gpio_pin_config_t QSPI_DATA2_config =
273 {
274 .outVal = 1,
275 .driveMode = CY_GPIO_DM_STRONG,
276 .hsiom = P11_4_SMIF_SPI_DATA2,
277 .intEdge = CY_GPIO_INTR_DISABLE,
278 .intMask = 0UL,
279 .vtrip = CY_GPIO_VTRIP_CMOS,
280 .slewRate = CY_GPIO_SLEW_FAST,
281 .driveSel = CY_GPIO_DRIVE_1_2,
282 .vregEn = 0UL,
283 .ibufMode = 0UL,
284 .vtripSel = 0UL,
285 .vrefSel = 0UL,
286 .vohSel = 0UL,
287 };
288 const cy_stc_gpio_pin_config_t QSPI_DATA1_config =
289 {
290 .outVal = 1,
291 .driveMode = CY_GPIO_DM_STRONG,
292 .hsiom = P11_5_SMIF_SPI_DATA1,
293 .intEdge = CY_GPIO_INTR_DISABLE,
294 .intMask = 0UL,
295 .vtrip = CY_GPIO_VTRIP_CMOS,
296 .slewRate = CY_GPIO_SLEW_FAST,
297 .driveSel = CY_GPIO_DRIVE_1_2,
298 .vregEn = 0UL,
299 .ibufMode = 0UL,
300 .vtripSel = 0UL,
301 .vrefSel = 0UL,
302 .vohSel = 0UL,
303 };
304 const cy_stc_gpio_pin_config_t QSPI_DATA0_config =
305 {
306 .outVal = 1,
307 .driveMode = CY_GPIO_DM_STRONG,
308 .hsiom = P11_6_SMIF_SPI_DATA0,
309 .intEdge = CY_GPIO_INTR_DISABLE,
310 .intMask = 0UL,
311 .vtrip = CY_GPIO_VTRIP_CMOS,
312 .slewRate = CY_GPIO_SLEW_FAST,
313 .driveSel = CY_GPIO_DRIVE_1_2,
314 .vregEn = 0UL,
315 .ibufMode = 0UL,
316 .vtripSel = 0UL,
317 .vrefSel = 0UL,
318 .vohSel = 0UL,
319 };
320 const cy_stc_gpio_pin_config_t QSPI_SCK_config =
321 {
322 .outVal = 1,
323 .driveMode = CY_GPIO_DM_STRONG_IN_OFF,
324 .hsiom = P11_7_SMIF_SPI_CLK,
325 .intEdge = CY_GPIO_INTR_DISABLE,
326 .intMask = 0UL,
327 .vtrip = CY_GPIO_VTRIP_CMOS,
328 .slewRate = CY_GPIO_SLEW_FAST,
329 .driveSel = CY_GPIO_DRIVE_1_2,
330 .vregEn = 0UL,
331 .ibufMode = 0UL,
332 .vtripSel = 0UL,
333 .vrefSel = 0UL,
334 .vohSel = 0UL,
335 };
336
Isr_SMIF(void)337 void Isr_SMIF(void)
338 {
339 Cy_SMIF_Interrupt(QSPIPort, &QSPI_context);
340 }
341
qspi_init_hardware()342 cy_en_smif_status_t qspi_init_hardware()
343 {
344 cy_en_smif_status_t st;
345
346
347 Cy_GPIO_Pin_Init(D3Port, D3Pin, &QSPI_DATA3_config);
348 Cy_GPIO_SetHSIOM(D3Port, D3Pin, D3MuxPort);
349
350 Cy_GPIO_Pin_Init(D2Port, D2Pin, &QSPI_DATA2_config);
351 Cy_GPIO_SetHSIOM(D2Port, D2Pin, D2MuxPort);
352
353 Cy_GPIO_Pin_Init(D1Port, D1Pin, &QSPI_DATA1_config);
354 Cy_GPIO_SetHSIOM(D1Port, D1Pin, D1MuxPort);
355
356 Cy_GPIO_Pin_Init(D0Port, D0Pin, &QSPI_DATA0_config);
357 Cy_GPIO_SetHSIOM(D0Port, D0Pin, D0MuxPort);
358
359 Cy_GPIO_Pin_Init(SCKPort, SCKPin, &QSPI_SCK_config);
360 Cy_GPIO_SetHSIOM(SCKPort, SCKPin, SCKMuxPort);
361
362 Cy_SysClk_ClkHfSetSource(CY_SYSCLK_CLKHF_IN_CLKPATH2, CY_SYSCLK_CLKHF_IN_CLKPATH0);
363 Cy_SysClk_ClkHfSetDivider(CY_SYSCLK_CLKHF_IN_CLKPATH2, CY_SMIF_SYSCLK_HFCLK_DIVIDER);
364 Cy_SysClk_ClkHfEnable(CY_SYSCLK_CLKHF_IN_CLKPATH2);
365
366 /*
367 * Setup the interrupt for the SMIF block. For the CM0 there
368 * is a two stage process to setup the interrupts.
369 */
370 Cy_SysInt_Init(&smifIntConfig, Isr_SMIF);
371
372 st = Cy_SMIF_Init(QSPIPort, &QSPI_config, 1000, &QSPI_context);
373 if (st != CY_SMIF_SUCCESS)
374 {
375 return st;
376 }
377 NVIC_EnableIRQ(smifIntConfig.intrSrc); /* Finally, Enable the SMIF interrupt */
378
379 Cy_SMIF_Enable(QSPIPort, &QSPI_context);
380
381 return CY_SMIF_SUCCESS;
382 }
383
qspi_get_memory_config(int index)384 cy_stc_smif_mem_config_t *qspi_get_memory_config(int index)
385 {
386 return smif_blk_config->memConfig[index];
387 }
388
qspi_get_device()389 SMIF_Type *qspi_get_device()
390 {
391 return QSPIPort;
392 }
393
qspi_get_context()394 cy_stc_smif_context_t *qspi_get_context()
395 {
396 return &QSPI_context;
397 }
398
qspi_init(cy_stc_smif_block_config_t * blk_config)399 cy_en_smif_status_t qspi_init(cy_stc_smif_block_config_t *blk_config)
400 {
401 cy_en_smif_status_t st;
402
403 st = qspi_init_hardware();
404 if (st == CY_SMIF_SUCCESS)
405 {
406 smif_blk_config = blk_config;
407 st = Cy_SMIF_MemInit(QSPIPort, smif_blk_config, &QSPI_context);
408 }
409 return st;
410 }
411
qspi_init_sfdp(uint32_t smif_id)412 cy_en_smif_status_t qspi_init_sfdp(uint32_t smif_id)
413 {
414 cy_en_smif_status_t stat = CY_SMIF_SUCCESS;
415
416 cy_stc_smif_mem_config_t **memCfg = smifBlockConfig_sfdp.memConfig;
417
418 GPIO_PRT_Type *SS_Port;
419 int SS_Pin;
420 en_hsiom_sel_t SS_MuxPort;
421
422 switch(smif_id)
423 {
424 case 1:
425 (*memCfg)->slaveSelect = CY_SMIF_SLAVE_SELECT_0;
426 break;
427 case 2:
428 (*memCfg)->slaveSelect = CY_SMIF_SLAVE_SELECT_1;
429 break;
430 case 3:
431 (*memCfg)->slaveSelect = CY_SMIF_SLAVE_SELECT_2;
432 break;
433 #if(CY_BOOTLOADER_SMIF_SS_CFG_NUM > 3)
434 case 4:
435 (*memCfg)->slaveSelect = CY_SMIF_SLAVE_SELECT_3;
436 break;
437 #endif
438 default:
439 stat = -1;
440 break;
441 }
442
443 if(CY_SMIF_SUCCESS == stat)
444 {
445 SS_Port = qspi_SS_Configuration[smif_id-1].SS_Port;
446 SS_Pin = qspi_SS_Configuration[smif_id-1].SS_Pin;
447 SS_MuxPort = qspi_SS_Configuration[smif_id-1].SS_Mux;
448
449 QSPI_SS_config.hsiom = SS_MuxPort;
450
451 Cy_GPIO_Pin_Init(SS_Port, SS_Pin, &QSPI_SS_config);
452 Cy_GPIO_SetHSIOM(SS_Port, SS_Pin, SS_MuxPort);
453
454 stat = qspi_init(&smifBlockConfig_sfdp);
455 }
456 return stat;
457 }
458
qspi_get_prog_size(void)459 uint32_t qspi_get_prog_size(void)
460 {
461 cy_stc_smif_mem_config_t **memCfg = smifBlockConfig_sfdp.memConfig;
462 return (*memCfg)->deviceCfg->programSize;
463 }
464
qspi_get_erase_size(void)465 uint32_t qspi_get_erase_size(void)
466 {
467 cy_stc_smif_mem_config_t **memCfg = smifBlockConfig_sfdp.memConfig;
468 return (*memCfg)->deviceCfg->eraseSize;
469 }
470
qspi_get_mem_size(void)471 uint32_t qspi_get_mem_size(void)
472 {
473 cy_stc_smif_mem_config_t **memCfg = smifBlockConfig_sfdp.memConfig;
474 return (*memCfg)->deviceCfg->memSize;
475 }
476
qspi_deinit(uint32_t smif_id)477 void qspi_deinit(uint32_t smif_id)
478 {
479 Cy_SMIF_MemDeInit(QSPIPort);
480
481 Cy_SMIF_Disable(QSPIPort);
482
483 Cy_SysClk_ClkHfDisable(CY_SYSCLK_CLKHF_IN_CLKPATH2);
484
485 NVIC_DisableIRQ(smifIntConfig.intrSrc);
486 Cy_SysInt_DisconnectInterruptSource(smifIntConfig.intrSrc, smifIntConfig.cm0pSrc);
487
488 Cy_GPIO_Port_Deinit(qspi_SS_Configuration[smif_id-1].SS_Port);
489 Cy_GPIO_Port_Deinit(SCKPort);
490 Cy_GPIO_Port_Deinit(D0Port);
491 Cy_GPIO_Port_Deinit(D1Port);
492 Cy_GPIO_Port_Deinit(D2Port);
493 Cy_GPIO_Port_Deinit(D3Port);
494 }
495