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