1 /**
2   ******************************************************************************
3   * @file    bflb_xip_sflash.c
4   * @version V1.0
5   * @date
6   * @brief   This file is the standard driver c file
7   ******************************************************************************
8   * @attention
9   *
10   * <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
11   *
12   * Redistribution and use in source and binary forms, with or without modification,
13   * are permitted provided that the following conditions are met:
14   *   1. Redistributions of source code must retain the above copyright notice,
15   *      this list of conditions and the following disclaimer.
16   *   2. Redistributions in binary form must reproduce the above copyright notice,
17   *      this list of conditions and the following disclaimer in the documentation
18   *      and/or other materials provided with the distribution.
19   *   3. Neither the name of Bouffalo Lab nor the names of its contributors
20   *      may be used to endorse or promote products derived from this software
21   *      without specific prior written permission.
22   *
23   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *
34   ******************************************************************************
35   */
36 
37 #include "bflb_common.h"
38 #include "bflb_xip_sflash.h"
39 
40 /** @addtogroup  BL628_Peripheral_Driver
41  *  @{
42  */
43 
44 /** @addtogroup  XIP_SFLASH
45  *  @{
46  */
47 
48 /** @defgroup  XIP_SFLASH_Private_Macros
49  *  @{
50  */
51 
52 /*@} end of group XIP_SFLASH_Private_Macros */
53 
54 /** @defgroup  XIP_SFLASH_Private_Types
55  *  @{
56  */
57 
58 /*@} end of group XIP_SFLASH_Private_Types */
59 
60 /** @defgroup  XIP_SFLASH_Private_Variables
61  *  @{
62  */
63 
64 /*@} end of group XIP_SFLASH_Private_Variables */
65 
66 /** @defgroup  XIP_SFLASH_Global_Variables
67  *  @{
68  */
69 
70 /*@} end of group XIP_SFLASH_Global_Variables */
71 
72 /** @defgroup  XIP_SFLASH_Private_Fun_Declaration
73  *  @{
74  */
75 
76 /*@} end of group XIP_SFLASH_Private_Fun_Declaration */
77 
78 /** @defgroup  XIP_SFLASH_Private_Functions
79  *  @{
80  */
81 
82 /****************************************************************************/ /**
83  * @brief  Save flash controller state
84  *
85  * @param  p_flash_cfg: Flash config pointer
86  * @param  offset: CPU XIP flash offset pointer
87  * @param  group: CPU group id 0 or 1
88  * @param  bank: Flash bank select
89  *
90  * @return BFLB_RET:0 means success and other value means error
91  *
92 *******************************************************************************/
93 __WEAK
bflb_xip_sflash_state_save(spi_flash_cfg_type * p_flash_cfg,uint32_t * offset,uint8_t group,uint8_t bank)94 int ATTR_TCM_SECTION bflb_xip_sflash_state_save(spi_flash_cfg_type *p_flash_cfg, uint32_t *offset,
95                                                     uint8_t group, uint8_t bank)
96 {
97     /* XIP_SFlash_Delay */
98     volatile uint32_t i = 32 * 2;
99 
100     while (i--)
101         ;
102 
103 #ifdef BFLB_SF_CTRL_SBUS2_ENABLE
104     if (bank == SF_CTRL_FLASH_BANK1) {
105         bflb_sf_ctrl_sbus2_replace(SF_CTRL_PAD2);
106     }
107 #endif
108     bflb_sf_ctrl_set_owner(SF_CTRL_OWNER_SAHB);
109     /* Exit form continous read for accepting command */
110     bflb_sflash_reset_continue_read(p_flash_cfg);
111     /* For disable command that is setting register instaed of send command, we need write enable */
112     bflb_sflash_disable_burst_wrap(p_flash_cfg);
113 #ifdef BFLB_SF_CTRL_32BITS_ADDR_ENABLE
114     /* Enable 32Bits addr mode again in case reset command make it reset */
115     bflb_sflash_set_32bits_addr_mode(p_flash_cfg, 1);
116 #endif
117     if ((p_flash_cfg->io_mode & 0x0f) == SF_CTRL_QO_MODE || (p_flash_cfg->io_mode & 0x0f) == SF_CTRL_QIO_MODE) {
118         /* Enable QE again in case reset command make it reset */
119         bflb_sflash_qspi_enable(p_flash_cfg);
120     }
121     /* Deburst again to make sure */
122     bflb_sflash_disable_burst_wrap(p_flash_cfg);
123 
124     /* Clear offset setting*/
125     *offset = bflb_sf_ctrl_get_flash_image_offset(group, bank);
126     bflb_sf_ctrl_set_flash_image_offset(0, group, bank);
127 
128     return 0;
129 }
130 
131 /****************************************************************************/ /**
132  * @brief  Restore flash controller state
133  *
134  * @param  p_flash_cfg: Flash config pointer
135  * @param  offset: CPU XIP flash offset
136  * @param  group: CPU group id 0 or 1
137  * @param  bank: Flash bank select
138  *
139  * @return BFLB_RET:0 means success and other value means error
140  *
141 *******************************************************************************/
142 __WEAK
bflb_xip_sflash_state_restore(spi_flash_cfg_type * p_flash_cfg,uint32_t offset,uint8_t group,uint8_t bank)143 int ATTR_TCM_SECTION bflb_xip_sflash_state_restore(spi_flash_cfg_type *p_flash_cfg, uint32_t offset,
144                                                        uint8_t group, uint8_t bank)
145 {
146     uint32_t tmp[1];
147     uint8_t io_mode = p_flash_cfg->io_mode & 0xf;
148 
149     bflb_sf_ctrl_set_flash_image_offset(offset, group, bank);
150 
151     if(((p_flash_cfg->io_mode>>4)&0x01) == 0) {
152         if((p_flash_cfg->io_mode&0x0f)==SF_CTRL_QO_MODE || (p_flash_cfg->io_mode&0x0f)==SF_CTRL_QIO_MODE) {
153             bflb_sflash_set_burst_wrap(p_flash_cfg);
154         }
155     }
156 #ifdef BFLB_SF_CTRL_32BITS_ADDR_ENABLE
157     bflb_sflash_set_32bits_addr_mode(p_flash_cfg, 1);
158 #endif
159     bflb_sflash_read(p_flash_cfg, io_mode, 1, 0x0, (uint8_t *)tmp, sizeof(tmp));
160     bflb_sflash_set_xip_cfg(p_flash_cfg, io_mode, 1, 0, 32, bank);
161 #ifdef BFLB_SF_CTRL_SBUS2_ENABLE
162     if (bank == SF_CTRL_FLASH_BANK1) {
163         bflb_sf_ctrl_sbus2_revoke_replace();
164     }
165 #endif
166 
167     return 0;
168 }
169 
170 /*@} end of group XIP_SFLASH_Private_Functions */
171 
172 /** @defgroup  XIP_SFLASH_Public_Functions
173  *  @{
174  */
175 
176 /****************************************************************************/ /**
177  * @brief  Erase flash one region
178  *
179  * @param  p_flash_cfg: Flash config pointer
180  * @param  start_addr: start address to erase
181  * @param  len: data length to erase
182  * @param  group: CPU group id 0 or 1
183  * @param  bank: Flash bank select
184  *
185  * @return BFLB_RET:0 means success and other value means error
186  *
187 *******************************************************************************/
188 __WEAK
bflb_xip_sflash_erase_need_lock(spi_flash_cfg_type * p_flash_cfg,uint32_t start_addr,int len,uint8_t group,uint8_t bank)189 int ATTR_TCM_SECTION bflb_xip_sflash_erase_need_lock(spi_flash_cfg_type *p_flash_cfg, uint32_t start_addr,
190                                                          int len, uint8_t group, uint8_t bank)
191 {
192     int stat = 0;
193     uint32_t offset = 0;
194     uint8_t aes_enable = 0;
195     uint8_t io_mode = p_flash_cfg->io_mode & 0xf;
196 
197     bflb_xip_sflash_opt_enter(&aes_enable);
198     stat = bflb_xip_sflash_state_save(p_flash_cfg, &offset, group, bank);
199 
200     if (stat != 0) {
201         bflb_sflash_set_xip_cfg(p_flash_cfg, io_mode, 1, 0, 32, bank);
202     } else {
203         stat = bflb_sflash_erase(p_flash_cfg, start_addr, start_addr + len - 1);
204         bflb_xip_sflash_state_restore(p_flash_cfg, offset, group, bank);
205     }
206 
207     bflb_xip_sflash_opt_exit(aes_enable);
208 
209     return stat;
210 }
211 
212 /****************************************************************************/ /**
213  * @brief  Program flash one region
214  *
215  * @param  p_flash_cfg: Flash config pointer
216  * @param  addr: start address to be programed
217  * @param  data: data pointer to be programed
218  * @param  len: data length to be programed
219  * @param  group: CPU group id 0 or 1
220  * @param  bank: Flash bank select
221  *
222  * @return BFLB_RET:0 means success and other value means error
223  *
224 *******************************************************************************/
225 __WEAK
bflb_xip_sflash_write_need_lock(spi_flash_cfg_type * p_flash_cfg,uint32_t addr,uint8_t * data,uint32_t len,uint8_t group,uint8_t bank)226 int ATTR_TCM_SECTION bflb_xip_sflash_write_need_lock(spi_flash_cfg_type *p_flash_cfg, uint32_t addr, uint8_t *data,
227                                                          uint32_t len, uint8_t group, uint8_t bank)
228 {
229     int stat = 0;
230     uint32_t offset = 0;
231     uint8_t aes_enable = 0;
232     uint8_t io_mode = p_flash_cfg->io_mode & 0xf;
233 
234     bflb_xip_sflash_opt_enter(&aes_enable);
235     stat = bflb_xip_sflash_state_save(p_flash_cfg, &offset, group, bank);
236 
237     if (stat != 0) {
238         bflb_sflash_set_xip_cfg(p_flash_cfg, io_mode, 1, 0, 32, bank);
239     } else {
240         stat = bflb_sflash_program(p_flash_cfg, io_mode, addr, data, len);
241         bflb_xip_sflash_state_restore(p_flash_cfg, offset, group, bank);
242     }
243 
244     bflb_xip_sflash_opt_exit(aes_enable);
245 
246     return stat;
247 }
248 
249 /****************************************************************************/ /**
250  * @brief  Read data from flash
251  *
252  * @param  p_flash_cfg: Flash config pointer
253  * @param  addr: flash read start address
254  * @param  data: data pointer to store data read from flash
255  * @param  len: data length to read
256  * @param  group: CPU group id 0 or 1
257  * @param  bank: Flash bank select
258  *
259  * @return BFLB_RET:0 means success and other value means error
260  *
261 *******************************************************************************/
262 __WEAK
bflb_xip_sflash_read_need_lock(spi_flash_cfg_type * p_flash_cfg,uint32_t addr,uint8_t * data,uint32_t len,uint8_t group,uint8_t bank)263 int ATTR_TCM_SECTION bflb_xip_sflash_read_need_lock(spi_flash_cfg_type *p_flash_cfg, uint32_t addr, uint8_t *data,
264                                                         uint32_t len, uint8_t group, uint8_t bank)
265 {
266     int stat = 0;
267     uint32_t offset = 0;
268     uint8_t aes_enable = 0;
269     uint8_t io_mode = p_flash_cfg->io_mode & 0xf;
270 
271     bflb_xip_sflash_opt_enter(&aes_enable);
272     stat = bflb_xip_sflash_state_save(p_flash_cfg, &offset, group, bank);
273 
274     if (stat != 0) {
275         bflb_sflash_set_xip_cfg(p_flash_cfg, io_mode, 1, 0, 32, bank);
276     } else {
277         stat = bflb_sflash_read(p_flash_cfg, io_mode, 0, addr, data, len);
278         bflb_xip_sflash_state_restore(p_flash_cfg, offset, group, bank);
279     }
280 
281     bflb_xip_sflash_opt_exit(aes_enable);
282 
283     return stat;
284 }
285 
286 /****************************************************************************/ /**
287  * @brief  Get Flash Jedec ID
288  *
289  * @param  p_flash_cfg: Flash config pointer
290  * @param  data: data pointer to store Jedec ID Read from flash
291  * @param  group: CPU group id 0 or 1
292  * @param  bank: Flash bank select
293  *
294  * @return BFLB_RET:0 means success and other value means error
295  *
296 *******************************************************************************/
297 __WEAK
bflb_xip_sflash_get_jedecid_need_lock(spi_flash_cfg_type * p_flash_cfg,uint8_t * data,uint8_t group,uint8_t bank)298 int ATTR_TCM_SECTION bflb_xip_sflash_get_jedecid_need_lock(spi_flash_cfg_type *p_flash_cfg, uint8_t *data,
299                                                                uint8_t group, uint8_t bank)
300 {
301     int stat = 0;
302     uint32_t offset = 0;
303     uint8_t aes_enable = 0;
304     uint8_t io_mode = p_flash_cfg->io_mode & 0xf;
305 
306     bflb_xip_sflash_opt_enter(&aes_enable);
307     stat = bflb_xip_sflash_state_save(p_flash_cfg, &offset, group, bank);
308 
309     if (stat != 0) {
310         bflb_sflash_set_xip_cfg(p_flash_cfg, io_mode, 1, 0, 32, bank);
311     } else {
312         bflb_sflash_get_jedecid(p_flash_cfg, data);
313         bflb_xip_sflash_state_restore(p_flash_cfg, offset, group, bank);
314     }
315 
316     bflb_xip_sflash_opt_exit(aes_enable);
317 
318     return 0;
319 }
320 
321 /****************************************************************************/ /**
322  * @brief  Get Flash Device ID
323  *
324  * @param  p_flash_cfg: Flash config pointer
325  * @param  is_32bits_addr: Is flash addr mode in 32-bits
326  * @param  data: data pointer to store Device ID Read from flash
327  * @param  group: CPU group id 0 or 1
328  * @param  bank: Flash bank select
329  *
330  * @return BFLB_RET:0 means success and other value means error
331  *
332 *******************************************************************************/
333 __WEAK
bflb_xip_sflash_get_deviceid_need_lock(spi_flash_cfg_type * p_flash_cfg,uint8_t is_32bits_addr,uint8_t * data,uint8_t group,uint8_t bank)334 int ATTR_TCM_SECTION bflb_xip_sflash_get_deviceid_need_lock(spi_flash_cfg_type *p_flash_cfg, uint8_t is_32bits_addr,
335                                                                 uint8_t *data, uint8_t group, uint8_t bank)
336 {
337     int stat = 0;
338     uint32_t offset = 0;
339     uint8_t aes_enable = 0;
340     uint8_t io_mode = p_flash_cfg->io_mode & 0xf;
341 
342     bflb_xip_sflash_opt_enter(&aes_enable);
343     stat = bflb_xip_sflash_state_save(p_flash_cfg, &offset, group, bank);
344 
345     if (stat != 0) {
346         bflb_sflash_set_xip_cfg(p_flash_cfg, io_mode, 1, 0, 32, bank);
347     } else {
348         bflb_sflash_get_deviceid(data, is_32bits_addr);
349         bflb_xip_sflash_state_restore(p_flash_cfg, offset, group, bank);
350     }
351 
352     bflb_xip_sflash_opt_exit(aes_enable);
353 
354     return 0;
355 }
356 
357 /****************************************************************************/ /**
358  * @brief  Get Flash Unique ID
359  *
360  * @param  p_flash_cfg: Flash config pointer
361  * @param  data: data pointer to store Device ID Read from flash
362  * @param  id_len: Unique id len
363  * @param  group: CPU group id 0 or 1
364  * @param  bank: Flash bank select
365  *
366  * @return BFLB_RET:0 means success and other value means error
367  *
368 *******************************************************************************/
369 __WEAK
bflb_xip_sflash_get_uniqueid_need_lock(spi_flash_cfg_type * p_flash_cfg,uint8_t * data,uint8_t id_len,uint8_t group,uint8_t bank)370 int ATTR_TCM_SECTION bflb_xip_sflash_get_uniqueid_need_lock(spi_flash_cfg_type *p_flash_cfg, uint8_t *data,
371                                                                 uint8_t id_len, uint8_t group, uint8_t bank)
372 {
373     int stat = 0;
374     uint32_t offset = 0;
375     uint8_t aes_enable = 0;
376     uint8_t io_mode = p_flash_cfg->io_mode & 0xf;
377 
378     bflb_xip_sflash_opt_enter(&aes_enable);
379     stat = bflb_xip_sflash_state_save(p_flash_cfg, &offset, group, bank);
380 
381     if (stat != 0) {
382         bflb_sflash_set_xip_cfg(p_flash_cfg, io_mode, 1, 0, 32, bank);
383     } else {
384         bflb_sflash_get_uniqueid(data, id_len);
385         bflb_xip_sflash_state_restore(p_flash_cfg, offset, group, bank);
386     }
387 
388     bflb_xip_sflash_opt_exit(aes_enable);
389 
390     return 0;
391 }
392 
393 /****************************************************************************//**
394  * @brief  Clear flash status register need lock
395  *
396  * @param  p_flash_cfg: Flash config pointer
397  * @param  group: CPU group id 0 or 1
398  * @param  bank: Flash bank select
399  *
400  * @return BFLB_RET:0 means success and other value means error
401  *
402 *******************************************************************************/
403 __WEAK
bflb_xip_sflash_clear_status_register_need_lock(spi_flash_cfg_type * p_flash_cfg,uint8_t group,uint8_t bank)404 int ATTR_TCM_SECTION bflb_xip_sflash_clear_status_register_need_lock(spi_flash_cfg_type *p_flash_cfg,
405                                                                      uint8_t group, uint8_t bank)
406 {
407     int stat = 0;
408     uint32_t offset = 0;
409     uint8_t aes_enable = 0;
410     uint8_t io_mode = p_flash_cfg->io_mode & 0xf;
411 
412     bflb_xip_sflash_opt_enter(&aes_enable);
413     stat = bflb_xip_sflash_state_save(p_flash_cfg, &offset, group, bank);
414 
415     if (stat != 0) {
416         bflb_sflash_set_xip_cfg(p_flash_cfg, io_mode, 1, 0, 32, bank);
417     } else {
418         stat = bflb_sflash_clear_status_register(p_flash_cfg);
419         bflb_xip_sflash_state_restore(p_flash_cfg, offset, group, bank);
420     }
421 
422     bflb_xip_sflash_opt_exit(aes_enable);
423 
424     return 0;
425 }
426 
427 /****************************************************************************/ /**
428  * @brief  Read data from flash via XIP
429  *
430  * @param  addr: flash read start address
431  * @param  data: data pointer to store data read from flash
432  * @param  len: data length to read
433  * @param  group: CPU group id 0 or 1
434  * @param  bank: Flash bank select
435  *
436  * @return BFLB_RET:0 means success and other value means error
437  *
438 *******************************************************************************/
439 __WEAK
bflb_xip_sflash_read_via_cache_need_lock(uint32_t addr,uint8_t * data,uint32_t len,uint8_t group,uint8_t bank)440 int ATTR_TCM_SECTION bflb_xip_sflash_read_via_cache_need_lock(uint32_t addr, uint8_t *data, uint32_t len,
441                                                                   uint8_t group, uint8_t bank)
442 {
443     uint32_t offset = 0;
444 
445     addr = addr & (BFLB_FLASH_XIP_END-BFLB_FLASH_XIP_BASE-1);
446     addr |= BFLB_FLASH_XIP_BASE;
447 
448     offset = bflb_sf_ctrl_get_flash_image_offset(group, bank);
449     bflb_sf_ctrl_set_flash_image_offset(0, group, bank);
450     /* Flash read */
451     arch_memcpy_fast(data, (void *)(uintptr_t)(addr - bflb_sf_ctrl_get_flash_image_offset(group, bank)), len);
452     bflb_sf_ctrl_set_flash_image_offset(offset, group, bank);
453 
454     return 0;
455 }
456 
457 /****************************************************************************/ /**
458  * @brief  XIP SFlash option save
459  *
460  * @param  aes_enable: AES enable status pointer
461  *
462  * @return None
463  *
464 *******************************************************************************/
465 __WEAK
bflb_xip_sflash_opt_enter(uint8_t * aes_enable)466 void ATTR_TCM_SECTION bflb_xip_sflash_opt_enter(uint8_t *aes_enable)
467 {
468     *aes_enable = bflb_sf_ctrl_is_aes_enable();
469 
470     if (*aes_enable) {
471         bflb_sf_ctrl_aes_disable();
472     }
473 }
474 
475 /****************************************************************************/ /**
476  * @brief  XIP SFlash option restore
477  *
478  * @param  aes_enable: AES enable status
479  *
480  * @return None
481  *
482 *******************************************************************************/
483 __WEAK
bflb_xip_sflash_opt_exit(uint8_t aes_enable)484 void ATTR_TCM_SECTION bflb_xip_sflash_opt_exit(uint8_t aes_enable)
485 {
486     if (aes_enable) {
487         bflb_sf_ctrl_aes_enable();
488     }
489 }
490 
491 /*@} end of group XIP_SFLASH_Public_Functions */
492 
493 /*@} end of group XIP_SFLASH */
494 
495 /*@} end of group BL628_Peripheral_Driver */
496