1 /*
2 // Copyright (C) 2022 Beken Corporation
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 #include <common/bk_include.h>
16 #include "bk_arm_arch.h"
17 #include <common/sys_config.h>
18 #include "flash_bypass.h"
19 #include "sys_driver.h"
20 #include "gpio_driver.h"
21 #include <driver/spi.h>
22 #include "spi_hal.h"
23
flash_bypass_init(void)24 void flash_bypass_init(void) {
25 char *text_ptr, temp_buf = 0;
26 uint32_t reg;
27
28 /*step 2, resident cache*/
29 REG_WRITE(SPI_R_CTRL(0), 0);
30 do {
31 text_ptr = (char *)flash_bypass_quad_enable;
32 for (uint32_t i = 0; i < CURRENT_ROUTINE_TEXT_SIZE; i ++)
33 temp_buf += text_ptr[i];
34
35 REG_WRITE(SPI_R_INT_STATUS(0), temp_buf);
36 } while (0);
37
38 /*step 3, config spi master*/
39 /* clear spi status*/
40 REG_WRITE(SPI_R_CTRL(0), 0);
41 reg = REG_READ(SPI_R_INT_STATUS(0));
42 REG_WRITE(SPI_R_INT_STATUS(0), reg);
43 REG_WRITE(SPI_R_CFG(0), 0);
44
45 spi_config_t config = {0};
46 config.role = SPI_ROLE_MASTER;
47 config.bit_width = SPI_BIT_WIDTH_8BITS;
48 config.polarity = 1;
49 config.phase = 1;
50 config.wire_mode = SPI_4WIRE_MODE;
51 config.baud_rate = 1000000;
52 config.bit_order = SPI_MSB_FIRST;
53 bk_spi_driver_init();
54 bk_spi_init(0, &config);
55
56 /*step 4, gpioi of SPI0 are set as high-impedance state or input state ,
57 for spi mux with them*/
58 gpio_dev_unmap(SPI0_LL_CSN_PIN);
59 gpio_dev_unmap(SPI0_LL_SCK_PIN);
60 gpio_dev_unmap(SPI0_LL_MOSI_PIN);
61 gpio_dev_unmap(SPI0_LL_MISO_PIN);
62 }
63
flash_bypass_quad_enable(void)64 __attribute__((section(".itcm_sec_code"))) void flash_bypass_quad_enable(void)
65 {
66 uint32_t reg;
67 uint32_t reg_ctrl, reg_dat;
68 uint32_t reg_stat, reg_cfg;
69 uint32_t int_status = 0;
70 uint32_t spi_status = 0;
71 volatile uint32_t i, j, delay_count;
72
73 int_status = rtos_disable_int();
74
75 /*step 1, save spi register configuration*/
76 reg_ctrl = REG_READ(SPI_R_CTRL(0));
77 reg_stat = REG_READ(SPI_R_INT_STATUS(0));
78 reg_dat = REG_READ(SPI_R_DATA(0));
79 reg_cfg = REG_READ(SPI_R_CFG(0));
80
81 flash_bypass_init();
82
83 /*step 5, switch flash interface to spi
84 * Pay attention to prefetch instruction destination, the text can not
85 * fetch from flash space after this timepoint.
86 */
87 sys_drv_set_cpu_storage_connect_op_select_flash_sel(1);
88
89 /*step 6, write enable for status register: 06H*/
90 reg = REG_READ(SPI_R_INT_STATUS(0));
91 REG_WRITE(SPI_R_INT_STATUS(0), reg);
92 REG_WRITE(SPI_R_CFG(0), SPI_CFG_TX_EN_ONE_BYTE);
93 REG_WRITE(SPI_R_DATA(0), FLASH_CMD_WR_EN_SR);
94
95 /*step 7, write cmd 31H, data 0x02*/
96 for(i = 0; i < 500; i++) {
97 spi_status = REG_READ(SPI_R_INT_STATUS(0));
98 if(0 != (spi_status & SPI_STATUS_TX_FINISH_INT)) {
99 break;
100 }
101 }
102 for(delay_count = 0; delay_count < 20000; delay_count ++)
103 {
104 for(j = 0; j < 8; j ++)
105 ;
106 }
107
108 REG_WRITE(SPI_R_CFG(0), 0);
109 reg = REG_READ(SPI_R_INT_STATUS(0));
110 REG_WRITE(SPI_R_INT_STATUS(0), reg);
111
112 REG_WRITE(SPI_R_CFG(0), SPI_CFG_TX_EN_TWO_BYTE);
113 REG_WRITE(SPI_R_DATA(0), FLASH_CMD_WR_SR);
114 REG_WRITE(SPI_R_DATA(0), FLASH_GD25Q32C_SR_QUAD_EN);
115
116 for(i = 0; i < 500; i++) {
117 spi_status = REG_READ(SPI_R_INT_STATUS(0));
118 if(0 != (spi_status & SPI_STATUS_TX_FINISH_INT)) {
119 break;
120 }
121 }
122 for(delay_count = 0; delay_count < 20000; delay_count ++)
123 {
124 for(j = 0; j < 8; j ++)
125 ;
126 }
127 REG_WRITE(SPI_R_CFG(0), 0);
128 reg = REG_READ(SPI_R_INT_STATUS(0));
129 REG_WRITE(SPI_R_INT_STATUS(0), reg);
130
131 /*step 8, switch flash interface to flash controller */
132 sys_drv_set_cpu_storage_connect_op_select_flash_sel(0);
133
134 /*step 9, restore spi register configuration*/
135 REG_WRITE(SPI_R_CTRL(0), reg_ctrl);
136 REG_WRITE(SPI_R_INT_STATUS(0), reg_stat);
137 REG_WRITE(SPI_R_DATA(0), reg_dat);
138 REG_WRITE(SPI_R_CFG(0), reg_cfg);
139 rtos_enable_int(int_status);
140 }
141
142
flash_bypass_quad_test(uint32_t quad_enable,uint32_t delay_cycle1,uint32_t delay_cycle2)143 __attribute__((section(".itcm_sec_code"))) void flash_bypass_quad_test(uint32_t quad_enable, uint32_t delay_cycle1, uint32_t delay_cycle2)
144 {
145 uint32_t reg;
146 uint32_t reg_ctrl, reg_dat;
147 uint32_t reg_stat, reg_cfg;
148 uint32_t int_status = 0;
149 uint32_t spi_status = 0;
150 volatile uint32_t i, j, delay_count;
151
152 int_status = rtos_disable_int();
153
154 /*step 1, save spi register configuration*/
155 reg_ctrl = REG_READ(SPI_R_CTRL(0));
156 reg_stat = REG_READ(SPI_R_INT_STATUS(0));
157 reg_dat = REG_READ(SPI_R_DATA(0));
158 reg_cfg = REG_READ(SPI_R_CFG(0));
159
160 flash_bypass_init();
161
162 /*step 5, switch flash interface to spi
163 * Pay attention to prefetch instruction destination, the text can not
164 * fetch from flash space after this timepoint.
165 */
166 sys_drv_set_cpu_storage_connect_op_select_flash_sel(1);
167
168 /*step 6, write enable for status register: 06H*/
169 reg = REG_READ(SPI_R_INT_STATUS(0));
170 REG_WRITE(SPI_R_INT_STATUS(0), reg);
171 REG_WRITE(SPI_R_CFG(0), SPI_CFG_TX_EN_ONE_BYTE);
172 REG_WRITE(SPI_R_DATA(0), FLASH_CMD_WR_EN_SR);
173
174 /*step 7, write cmd 31H, data 0x02*/
175 for(i = 0; i < delay_cycle1; i++) {
176 spi_status = REG_READ(SPI_R_INT_STATUS(0));
177 if(0 != (spi_status & SPI_STATUS_TX_FINISH_INT)) {
178 break;
179 }
180 }
181 for(delay_count = 0; delay_count < delay_cycle2; delay_count ++)
182 {
183 for(j = 0; j < 8; j ++)
184 ;
185 }
186
187 REG_WRITE(SPI_R_CFG(0), 0);
188 reg = REG_READ(SPI_R_INT_STATUS(0));
189 REG_WRITE(SPI_R_INT_STATUS(0), reg);
190
191 REG_WRITE(SPI_R_CFG(0), SPI_CFG_TX_EN_TWO_BYTE);
192 REG_WRITE(SPI_R_DATA(0), FLASH_CMD_WR_SR);
193 if (quad_enable) {
194 REG_WRITE(SPI_R_DATA(0), FLASH_GD25Q32C_SR_QUAD_EN);
195 } else {
196 REG_WRITE(SPI_R_DATA(0), 0);
197 }
198
199 for(i = 0; i < delay_cycle1; i++) {
200 spi_status = REG_READ(SPI_R_INT_STATUS(0));
201 if(0 != (spi_status & SPI_STATUS_TX_FINISH_INT)) {
202 break;
203 }
204 }
205 for(delay_count = 0; delay_count < delay_cycle2; delay_count ++)
206 {
207 for(j = 0; j < 8; j ++)
208 ;
209 }
210 REG_WRITE(SPI_R_CFG(0), 0);
211 reg = REG_READ(SPI_R_INT_STATUS(0));
212 REG_WRITE(SPI_R_INT_STATUS(0), reg);
213
214 /*step 8, switch flash interface to flash controller */
215 sys_drv_set_cpu_storage_connect_op_select_flash_sel(0);
216
217 /*step 9, restore spi register configuration*/
218 REG_WRITE(SPI_R_CTRL(0), reg_ctrl);
219 REG_WRITE(SPI_R_INT_STATUS(0), reg_stat);
220 REG_WRITE(SPI_R_DATA(0), reg_dat);
221 REG_WRITE(SPI_R_CFG(0), reg_cfg);
222 rtos_enable_int(int_status);
223 }
224