• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * Description: Provides sfc port template \n
16  *
17  * History: \n
18  * 2022-11-30, Create file. \n
19  */
20 #include "hal_sfc_v150.h"
21 #ifndef BUILD_NOOSAL
22 #include "soc_osal.h"
23 #endif
24 #include "debug_print.h"
25 #include "hal_sfc_v150_regs_op.h"
26 #include "osal_interrupt.h"
27 #include "securec.h"
28 #include "tcxo.h"
29 #include "sfc.h"
30 #include "sfc_porting.h"
31 #include "hal_sfc.h"
32 #include "sfc_protect_gd25q32.h"
33 #include "sfc_protect.h"
34 
35 #define SR1_BPX_MASK 0x7C
36 #define SR2_CMP_MASK 0x40
37 
38 #define FLASH_PROTECT_NONE_MASK         0x00
39 #define FLASH_PROTECT_ALL_MASK          0x1C
40 
41 #define SPI_CMD_WREN             0x06
42 #define SPI_CMD_WRVSR            0x50
43 
44 #define STANDARD_SPI             0x0
45 
46 #define ENABLE                   0x1
47 #define DISABLE                  0x0
48 
49 #define READ_MODE                0x1
50 #define WRITE_MODE               0x0
51 
52 typedef struct {
53     uint8_t sr2; // value of sr2
54     uint8_t sr1; // value of sr1
55     uint32_t start;
56     uint32_t end;
57 } sfc_protect_cfg_t;
58 
59 #define FLASH_CHIP_PROTECT_4K       0x001000
60 #define FLASH_CHIP_PROTECT_8K       0x002000
61 #define FLASH_CHIP_PROTECT_16K      0x004000
62 #define FLASH_CHIP_PROTECT_32K      0x008000
63 #define FLASH_CHIP_PROTECT_64K      0x010000
64 #define FLASH_CHIP_PROTECT_128K     0x020000
65 #define FLASH_CHIP_PROTECT_256K     0x040000
66 #define FLASH_CHIP_PROTECT_512K     0x080000
67 #define FLASH_CHIP_PROTECT_1M       0x100000
68 #define FLASH_CHIP_PROTECT_2M       0x200000
69 #define FLASH_CHIP_PROTECT_3M       0x300000
70 #define FLASH_CHIP_PROTECT_3584K    0x380000 // 512K
71 #define FLASH_CHIP_PROTECT_3840K    0x3C0000 // 256K
72 #define FLASH_CHIP_PROTECT_3968K    0x3E0000 // 128K
73 #define FLASH_CHIP_PROTECT_4032K    0x3F0000 // 64K
74 #define FLASH_CHIP_PROTECT_4064K    0x3F8000 // 32K
75 #define FLASH_CHIP_PROTECT_4080K    0x3FC000 // 16K
76 #define FLASH_CHIP_PROTECT_4088K    0x3FE000 // 8K
77 #define FLASH_CHIP_PROTECT_4092K    0x3FF000 // 4K
78 
79 /**
80  * 可写地址区间,前闭后开,[xxx, yyy)
81  * 配置必须按照放开写区间的大小,从小到大手动排序
82  */
83 #if defined FLASH_REGION_CFG_LOADERBOOT
84 static const sfc_protect_cfg_t g_sfc_protect_cfg[] ={
85     {0x02, 0x28, FLASH_CHIP_PROTECT_128K, FLASH_CHIP_PROTECT_END}, // 保护前两个Block 0&1
86     {0x02, 0x78, FLASH_CHIP_PROTECT_32K, FLASH_CHIP_PROTECT_END}, // 保护前32K
87     {0x02, 0x00, 0x0, FLASH_CHIP_PROTECT_END}, // 全片放开, 烧录时需要写前32K
88 };
89 
90 #elif defined FLASH_REGION_CFG_FLASHBOOT
91 static const sfc_protect_cfg_t g_sfc_protect_cfg[] ={
92     {0x02, 0x28, FLASH_CHIP_PROTECT_128K, FLASH_CHIP_PROTECT_END}, // 保护前两个Block 0&1
93 };
94 
95 #else // APP
96 static const sfc_protect_cfg_t g_sfc_protect_cfg[] ={
97 #ifdef _PRE_WLAN_FEATURE_MFG_TEST
98     {0x02, 0x28, FLASH_CHIP_PROTECT_128K, FLASH_CHIP_PROTECT_END}, // 保护前两个Block 0&1
99     {0x02, 0x78, FLASH_CHIP_PROTECT_32K, FLASH_CHIP_PROTECT_END}, // 保护前32K
100 #else
101     {0x42, 0x4C, FLASH_CHIP_PROTECT_4080K, FLASH_CHIP_PROTECT_END}, // 放开最后16K
102     {0x42, 0x58, FLASH_CHIP_PROTECT_4064K, FLASH_CHIP_PROTECT_END}, // 放开最后32K
103     {0x42, 0x10, FLASH_CHIP_PROTECT_3584K, FLASH_CHIP_PROTECT_END}, // 保护前7/8 (剩余后8个Block)
104     {0x42, 0x14, FLASH_CHIP_PROTECT_3M, FLASH_CHIP_PROTECT_END}, // 保护前3/4 (3M)
105     {0x02, 0x38, FLASH_CHIP_PROTECT_2M, FLASH_CHIP_PROTECT_END}, // 保护前1/2 (2M)
106     {0x02, 0x28, FLASH_CHIP_PROTECT_128K, FLASH_CHIP_PROTECT_END}, // 保护前两个Block 0&1
107 #endif // end of _PRE_WLAN_FEATURE_MFG_TEST
108 };
109 #endif // end of APP
110 #define SFC_PROTECT_CFG_NUMS (sizeof(g_sfc_protect_cfg) / sizeof(g_sfc_protect_cfg[0]))
111 
112 // 地址区间,前闭后开
sfc_port_find_addr_protect_cfg(uint32_t start_addr,uint32_t end_addr)113 static sfc_protect_cfg_t const *sfc_port_find_addr_protect_cfg(uint32_t start_addr, uint32_t end_addr)
114 {
115     // g_sfc_protect_cfg 中的配置必须按照放开写区间的大小,从小到大手动排序
116     for (uint32_t i = 0; i < SFC_PROTECT_CFG_NUMS; i++) {
117         if ((g_sfc_protect_cfg[i].start <= start_addr) &&
118             (g_sfc_protect_cfg[i].end >= end_addr)) {
119             return &g_sfc_protect_cfg[i];
120         }
121     }
122     return NULL;
123 }
124 
125 #ifdef BUILD_NOOSAL
126 // 该接口在 hal_sfc_v150.c 是 STATIC
hal_sfc_regs_wait_ready(uint8_t wip_bit)127 errcode_t hal_sfc_regs_wait_ready(uint8_t wip_bit)
128 {
129     uint32_t dead_line = 0;
130     uint32_t timeout = sfc_port_get_delay_times();
131     uint32_t delay = sfc_port_get_delay_once_time();
132     hal_spi_opreation_t hal_opreation = {0};
133     hal_opreation.opt.cmd = SPI_CMD_RDSR_1;
134     hal_opreation.opt.iftype = STANDARD_SPI;
135     hal_opreation.data_size = 1;
136     hal_opreation.dummy_byte = 0;
137 
138     /* 轮询策略修改:每次x微秒,轮询n次 */
139     do {
140         hal_sfc_regs_set_opt(&hal_opreation);
141         hal_sfc_regs_set_opt_attr(READ_MODE, ENABLE, DISABLE);
142         hal_sfc_regs_wait_config();
143         uint32_t reg_val = hal_sfc_regs_get_databuf(0);
144         if (((reg_val >> wip_bit) & 0x1) == 0) {
145             return ERRCODE_SUCC;
146         }
147         uapi_tcxo_delay_us(delay);
148     }while (dead_line++ < timeout);
149 
150     return ERRCODE_SFC_FLASH_TIMEOUT_WAIT_READY;
151 }
152 #else
153 errcode_t hal_sfc_regs_wait_ready(uint8_t wip_bit);
154 #endif
155 
sfc_port_sr_enable_write(bool is_volatile)156 static void sfc_port_sr_enable_write(bool is_volatile)
157 {
158     hal_spi_opreation_t hal_opreation;
159 
160     // 如果是易失性写入,需要使用50H命令
161     //       非易失性写入,需要使用06H命令
162     // 50H: Write Enable for Volatile Status Register
163     // The 50H must be issued prior to a 01H/31H/11H
164     hal_opreation.opt.cmd_support = SPI_CMD_SUPPORT;
165     hal_opreation.opt.cmd = is_volatile ? SPI_CMD_WRVSR : SPI_CMD_WREN;
166     hal_opreation.opt.iftype = STANDARD_SPI;
167     hal_opreation.opt.size = 0x0;
168     hal_opreation.data_size = 0x0;
169     hal_opreation.dummy_byte = 0x0;
170 
171 #ifndef BUILD_NOOSAL
172     hal_sfc_regs_set_opt(hal_opreation); // ROM化的接口
173 #else
174     // ROM化后,函数参数有变化,flashboot和ssb中用的是非ROM的接口
175     hal_sfc_regs_set_opt(&hal_opreation);
176 #endif
177 
178     hal_sfc_regs_set_opt_attr(WRITE_MODE, DISABLE, DISABLE); // cmd starts to be sent here
179     hal_sfc_regs_wait_config();
180 }
181 
sfc_port_do_write_sr(uint8_t cmd,uint8_t data)182 static void sfc_port_do_write_sr(uint8_t cmd, uint8_t data)
183 {
184     hal_spi_opreation_t hal_opreation;
185     cmd_databuf_t databuf;
186 
187     // 01H/31H/11H: Write Status Register (WRSRn) (01H/31H/11H)
188     // Any other commands can’t be inserted between 01H/31H/11H and 50H
189     hal_opreation.opt.cmd_support = SPI_CMD_SUPPORT;
190     hal_opreation.opt.cmd = cmd;
191     hal_opreation.opt.iftype = STANDARD_SPI;
192     hal_opreation.opt.size = 0x0;
193     hal_opreation.data_size = 0x1;
194     hal_opreation.dummy_byte = 0x0;
195 
196     databuf.d32 = 0;
197     databuf.b.databyte[0] = data;
198     hal_sfc_regs_set_databuf(0, databuf.d32);
199 
200 #ifndef BUILD_NOOSAL
201     hal_sfc_regs_set_opt(hal_opreation); // ROM化的接口
202 #else
203     // ROM化后,函数参数有变化,flashboot和ssb中用的是非ROM的接口
204     hal_sfc_regs_set_opt(&hal_opreation);
205 #endif
206 
207     hal_sfc_regs_set_opt_attr(WRITE_MODE, ENABLE, DISABLE); // cmd starts to be sent here
208     hal_sfc_regs_wait_config();
209     return;
210 }
211 
212 /**
213  * @brief  写状态寄存器。
214  * @param  [in]  is_volatile 是否是易失性写入。
215  *                True: 易失性写入, 掉电后配置丢失。
216  *                False: 非易失性写入, 掉电后配置不丢失。
217  * @param  [in]  cmd 命令字可以是:01H/31H/11H。
218  *                    01H: 写 SR1
219  *                    31H: 写 SR2
220  *                    11H: 写 SR3
221  * @param  [in]  data 待写入的SR寄存器的数据。
222  * @retval ERRCODE_SUCC 成功。
223  * @retval Other        失败,参考 @ref errcode_t 。
224  * @endif
225  */
sfc_port_write_sr(bool is_volatile,uint8_t cmd,uint8_t data)226 void sfc_port_write_sr(bool is_volatile, uint8_t cmd, uint8_t data)
227 {
228     hal_sfc_regs_wait_ready(0x0);
229     sfc_port_sr_enable_write(is_volatile);
230     sfc_port_do_write_sr(cmd, data);
231 }
232 
233 /**
234  * @brief  读取状态寄存器的值。
235  * @param  [in] cmd 命令字可以是:05H/35H/15H。
236  *                   05H: 读 SR1
237  *                   35H: 读 SR2
238  *                   15H: 读 SR3
239  * @retval 读取到的SR中的值。
240  * @endif
241  */
sfc_port_read_sr(uint32_t cmd)242 uint32_t sfc_port_read_sr(uint32_t cmd)
243 {
244     hal_spi_opreation_t hal_opreation;
245     hal_opreation.opt.cmd = cmd;
246     hal_opreation.opt.iftype = STANDARD_SPI;
247     hal_opreation.data_size = 1;
248     hal_opreation.dummy_byte = 0;
249 
250     hal_sfc_regs_wait_ready(0x0);
251 #ifndef BUILD_NOOSAL
252     hal_sfc_regs_set_opt(hal_opreation); // ROM化的接口
253 #else
254     // ROM化后,函数参数有变化,flashboot和ssb中用的是非ROM的接口
255     hal_sfc_regs_set_opt(&hal_opreation);
256 #endif
257     hal_sfc_regs_set_opt_attr(READ_MODE, ENABLE, DISABLE);
258     hal_sfc_regs_wait_config();
259     return hal_sfc_regs_get_databuf(0);
260 }
261 
sfc_port_block_protect_disable(uint32_t start_addr,uint32_t end_addr)262 static void sfc_port_block_protect_disable(uint32_t start_addr, uint32_t end_addr)
263 {
264     sfc_protect_cfg_t const *cfg = sfc_port_find_addr_protect_cfg(start_addr, end_addr);
265     if (cfg != NULL) {
266         sfc_port_write_sr(true, SPI_CMD_WRSR_1, cfg->sr1);
267         sfc_port_write_sr(true, SPI_CMD_WRSR_2, cfg->sr2);
268     }
269 }
270 
sfc_port_block_protect_enable(void)271 static void sfc_port_block_protect_enable(void)
272 {
273     sfc_port_write_sr(true, SPI_CMD_WRSR_1, SR1_VALID_VAL);
274     sfc_port_write_sr(true, SPI_CMD_WRSR_2, SR2_VALID_VAL);
275 }
276 
277 // 地址区间,前闭后开[xxx, xxx)
sfc_port_write_lock(uint32_t start_addr,uint32_t end_addr)278 uint32_t sfc_port_write_lock(uint32_t start_addr, uint32_t end_addr)
279 {
280 #ifndef BUILD_NOOSAL
281     uint32_t lock_sts = osal_irq_lock();
282     sfc_port_block_protect_disable(start_addr, end_addr);
283     return lock_sts;
284 #else
285     sfc_port_block_protect_disable(start_addr, end_addr);
286     return 0;
287 #endif
288 }
289 
sfc_port_write_unlock(uint32_t lock_sts)290 void sfc_port_write_unlock(uint32_t lock_sts)
291 {
292 #ifndef BUILD_NOOSAL
293     sfc_port_block_protect_enable();
294     osal_irq_restore(lock_sts);
295 #else
296     unused(lock_sts);
297     sfc_port_block_protect_enable();
298 #endif
299 }
300 
301 #define FLASH_GD25Q32           0x1640C8
sfc_port_fix_sr(void)302 errcode_t sfc_port_fix_sr(void)
303 {
304     uint32_t flash_id = 0;
305     errcode_t err;
306 
307     err = hal_sfc_get_flash_id(&flash_id);
308     if (err != ERRCODE_SUCC) {
309         return err;
310     }
311 
312     if (flash_id == FLASH_GD25Q32) {
313         return sfc_port_fix_sr_gd25q32();
314     }
315 
316     return ERRCODE_NOT_SUPPORT;
317 }
318 
319