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