1 /*
2  * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <sys/param.h>
8 #include "sdkconfig.h"
9 #include "string.h"
10 #include "esp_attr.h"
11 #include "esp_err.h"
12 #include "esp_types.h"
13 #include "esp_log.h"
14 #include "soc/spi_mem_reg.h"
15 #include "hal/mspi_timing_tuning_ll.h"
16 #include "../../mspi_timing_config.h"
17 #include "bootloader_flash.h"
18 #include "esp32s3/rom/spi_flash.h"
19 #include "esp32s3/rom/opi_flash.h"
20 
21 #define OPI_PSRAM_SYNC_READ           0x0000
22 #define OPI_PSRAM_SYNC_WRITE          0x8080
23 #define OCT_PSRAM_RD_DUMMY_NUM        (2*(10-1))
24 #define OCT_PSRAM_WR_DUMMY_NUM        (2*(5-1))
25 
26 #define QPI_PSRAM_FAST_READ            0XEB
27 #define QPI_PSRAM_WRITE                0X38
28 #define QPI_PSRAM_FAST_READ_DUMMY      6
29 
30 #define NOT_INIT_INT                  127
31 
32 //-------------------------------------MSPI Clock Setting-------------------------------------//
mspi_timing_config_get_core_clock(void)33 mspi_timing_config_core_clock_t mspi_timing_config_get_core_clock(void)
34 {
35     switch (MSPI_TIMING_CORE_CLOCK_MHZ) {
36         case 80:
37             return MSPI_TIMING_CONFIG_CORE_CLOCK_80M;
38         case 120:
39             return MSPI_TIMING_CONFIG_CORE_CLOCK_120M;
40         case 160:
41             return MSPI_TIMING_CONFIG_CORE_CLOCK_160M;
42         case 240:
43             return MSPI_TIMING_CONFIG_CORE_CLOCK_240M;
44         default:
45             abort();
46     }
47 }
48 
mspi_timing_config_set_core_clock(uint8_t spi_num,mspi_timing_config_core_clock_t core_clock)49 void mspi_timing_config_set_core_clock(uint8_t spi_num, mspi_timing_config_core_clock_t core_clock)
50 {
51     uint32_t reg_val = 0;
52 
53     switch (core_clock) {
54         case MSPI_TIMING_CONFIG_CORE_CLOCK_80M:
55             reg_val = 0;
56             break;
57         case MSPI_TIMING_CONFIG_CORE_CLOCK_120M:
58             reg_val = 1;
59             break;
60         case MSPI_TIMING_CONFIG_CORE_CLOCK_160M:
61             reg_val = 2;
62             break;
63         case MSPI_TIMING_CONFIG_CORE_CLOCK_240M:
64             reg_val = 3;
65             break;
66         default:
67             abort();
68     }
69 
70     mspi_timing_ll_set_core_clock_divider(spi_num, reg_val);
71 }
72 
mspi_timing_config_set_flash_clock(uint8_t spi_num,uint32_t freqdiv)73 void mspi_timing_config_set_flash_clock(uint8_t spi_num, uint32_t freqdiv)
74 {
75     assert(freqdiv > 0);
76     mspi_timing_ll_set_flash_clock(spi_num, freqdiv);
77 }
78 
mspi_timing_config_set_psram_clock(uint8_t spi_num,uint32_t freqdiv)79 void mspi_timing_config_set_psram_clock(uint8_t spi_num, uint32_t freqdiv)
80 {
81     mspi_timing_ll_set_psram_clock(spi_num, freqdiv);
82 }
83 
84 /////////////////////////////////////////TIMING TUNING IS NEEDED//////////////////////////////////////////////
85 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
86 #if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
87 //If one of the FLASH / PSRAM or both of them need timing tuning, we should build following code
88 typedef enum {
89     PSRAM_CMD_QPI,
90     PSRAM_CMD_SPI,
91 } psram_cmd_mode_t;
92 
93 static uint8_t s_rom_flash_extra_dummy[2] = {NOT_INIT_INT, NOT_INIT_INT};
94 
95 #if CONFIG_SPIRAM_MODE_QUAD
96 static uint8_t s_psram_extra_dummy;
97 extern void psram_exec_cmd(int spi_num, psram_cmd_mode_t mode,
98                            uint32_t cmd, int cmd_bit_len,
99                            uint32_t addr, int addr_bit_len,
100                            int dummy_bits,
101                            uint8_t* mosi_data, int mosi_bit_len,
102                            uint8_t* miso_data, int miso_bit_len,
103                            uint32_t cs_mask,
104                            bool is_write_erase_operation);
105 #endif
106 
107 //-------------------------------------FLASH timing tuning register config-------------------------------------//
mspi_timing_config_flash_set_din_mode_num(uint8_t spi_num,uint8_t din_mode,uint8_t din_num)108 void mspi_timing_config_flash_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)
109 {
110     mspi_timing_ll_set_flash_din_mode(spi_num, din_mode);
111     mspi_timing_ll_set_flash_din_num(spi_num, din_num);
112 }
113 
spi_timing_config_get_dummy(void)114 static uint32_t spi_timing_config_get_dummy(void)
115 {
116     mspi_timing_ll_flash_mode_t mode = mspi_timing_ll_get_flash_mode(0);
117     if (mode == MSPI_TIMING_LL_FLASH_OPI_MODE) {
118         abort();
119     }
120 
121 #if CONFIG_SPI_FLASH_HPM_DC_ON
122     if (spi_flash_hpm_dummy_adjust()) { // HPM-DC is enabled
123         const spi_flash_hpm_dummy_conf_t *hpm_dummy = spi_flash_hpm_get_dummy();
124         switch (mode) {
125             case MSPI_TIMING_LL_FLASH_QIO_MODE:
126                 return hpm_dummy->qio_dummy - 1;
127             case MSPI_TIMING_LL_FLASH_QUAD_MODE:
128                 return hpm_dummy->qout_dummy - 1;
129             case MSPI_TIMING_LL_FLASH_DIO_MODE:
130                 return hpm_dummy->dio_dummy - 1;
131             case MSPI_TIMING_LL_FLASH_DUAL_MODE:
132                 return hpm_dummy->dout_dummy - 1;
133             case MSPI_TIMING_LL_FLASH_FAST_MODE:
134                 return hpm_dummy->fastrd_dummy - 1;
135             case MSPI_TIMING_LL_FLASH_SLOW_MODE:
136                 return 0;
137             default:
138                 abort();
139         }
140     } else
141 #endif
142     { // HPM-DC is not enabled
143         switch (mode) {
144             case MSPI_TIMING_LL_FLASH_QIO_MODE:
145                 return SPI1_R_QIO_DUMMY_CYCLELEN;
146             case MSPI_TIMING_LL_FLASH_QUAD_MODE:
147                 return SPI1_R_FAST_DUMMY_CYCLELEN;
148             case MSPI_TIMING_LL_FLASH_DIO_MODE:
149                 return SPI1_R_DIO_DUMMY_CYCLELEN;
150             case MSPI_TIMING_LL_FLASH_DUAL_MODE:
151                 return SPI1_R_FAST_DUMMY_CYCLELEN;
152             case MSPI_TIMING_LL_FLASH_FAST_MODE:
153                 return SPI1_R_FAST_DUMMY_CYCLELEN;
154             case MSPI_TIMING_LL_FLASH_SLOW_MODE:
155                 return 0;
156             default:
157                 abort();
158         }
159     }
160 }
161 
mspi_timing_config_flash_set_extra_dummy(uint8_t spi_num,uint8_t extra_dummy)162 void mspi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
163 {
164     if (bootloader_flash_is_octal_mode_enabled()) {
165         mspi_timing_ll_set_octal_flash_extra_dummy(spi_num, extra_dummy);
166         return;
167     }
168     /**
169      * HW workaround:
170      * The `SPI_MEM_TIMING_CALI_REG` register is only used for OPI on 728
171      * Here we only need to update this global variable for extra dummy. Since we use the ROM Flash API, which will set the dummy based on this.
172      * We only initialise the SPI0. And leave the SPI1 for flash driver to configure.
173      */
174     if (s_rom_flash_extra_dummy[spi_num] == NOT_INIT_INT) {
175         s_rom_flash_extra_dummy[spi_num] = g_rom_spiflash_dummy_len_plus[spi_num];
176     }
177     g_rom_spiflash_dummy_len_plus[spi_num] = s_rom_flash_extra_dummy[spi_num] + extra_dummy;
178 
179     // Only Quad Flash will run into this branch.
180     uint32_t dummy = spi_timing_config_get_dummy();
181     mspi_timing_ll_set_quad_flash_dummy(spi_num, dummy + g_rom_spiflash_dummy_len_plus[spi_num]);
182 }
183 
184 //-------------------------------------PSRAM timing tuning register config-------------------------------------//
mspi_timing_config_psram_set_din_mode_num(uint8_t spi_num,uint8_t din_mode,uint8_t din_num)185 void mspi_timing_config_psram_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)
186 {
187     mspi_timing_ll_set_psram_din_mode(spi_num, din_mode);
188     mspi_timing_ll_set_psram_din_num(spi_num, din_num);
189 }
190 
mspi_timing_config_psram_set_extra_dummy(uint8_t spi_num,uint8_t extra_dummy)191 void mspi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
192 {
193 #if CONFIG_SPIRAM_MODE_OCT
194     mspi_timing_ll_set_octal_psram_extra_dummy(spi_num, extra_dummy);
195 #elif CONFIG_SPIRAM_MODE_QUAD
196     //HW workaround: Use normal dummy register to set extra dummy, the calibration dedicated extra dummy register doesn't work for quad mode
197     mspi_timing_ll_set_quad_psram_dummy(spi_num, (QPI_PSRAM_FAST_READ_DUMMY + extra_dummy - 1));
198 #endif
199 }
200 
201 //-------------------------------------------FLASH/PSRAM Read/Write------------------------------------------//
mspi_timing_config_flash_read_data(uint8_t * buf,uint32_t addr,uint32_t len)202 void mspi_timing_config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
203 {
204     if (bootloader_flash_is_octal_mode_enabled()) {
205         // note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state.
206         // but after we change the timing settings, we might not read correct idle status via RDSR.
207         // so, here we should use a read API that won't check idle status.
208         mspi_timing_ll_clear_fifo(1);
209         esp_rom_opiflash_read_raw(addr, buf, len);
210     } else {
211         esp_rom_spiflash_read(addr, (uint32_t *)buf, len);
212     }
213 }
214 
s_psram_write_data(uint8_t * buf,uint32_t addr,uint32_t len)215 static void s_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
216 {
217 #if CONFIG_SPIRAM_MODE_OCT
218     esp_rom_opiflash_exec_cmd(1, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
219                             OPI_PSRAM_SYNC_WRITE, 16,
220                             addr, 32,
221                             OCT_PSRAM_WR_DUMMY_NUM,
222                             buf, len * 8,
223                             NULL, 0,
224                             BIT(1),
225                             false);
226 #elif CONFIG_SPIRAM_MODE_QUAD
227     psram_exec_cmd(1, 0,
228                    QPI_PSRAM_WRITE, 8,
229                    addr, 24,
230                    0,
231                    buf, len * 8,
232                    NULL, 0,
233                    SPI_MEM_CS1_DIS_M,
234                    false);
235 #endif
236 }
237 
s_psram_read_data(uint8_t * buf,uint32_t addr,uint32_t len)238 static void s_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
239 {
240 #if CONFIG_SPIRAM_MODE_OCT
241     mspi_timing_ll_clear_fifo(1);
242     esp_rom_opiflash_exec_cmd(1, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
243                             OPI_PSRAM_SYNC_READ, 16,
244                             addr, 32,
245                             OCT_PSRAM_RD_DUMMY_NUM,
246                             NULL, 0,
247                             buf, len * 8,
248                             BIT(1),
249                             false);
250 #elif CONFIG_SPIRAM_MODE_QUAD
251     psram_exec_cmd(1, 0,
252                    QPI_PSRAM_FAST_READ, 8,
253                    addr, 24,
254                    QPI_PSRAM_FAST_READ_DUMMY + s_psram_extra_dummy,
255                    NULL, 0,
256                    buf, len * 8,
257                    SPI_MEM_CS1_DIS_M,
258                    false);
259 #endif
260 }
261 
s_psram_execution(uint8_t * buf,uint32_t addr,uint32_t len,bool is_read)262 static void s_psram_execution(uint8_t *buf, uint32_t addr, uint32_t len, bool is_read)
263 {
264     while (len) {
265         uint32_t length = MIN(len, 32);
266         if (is_read) {
267             s_psram_read_data(buf, addr, length);
268         } else {
269             s_psram_write_data(buf, addr, length);
270         }
271         addr += length;
272         buf += length;
273         len -= length;
274     }
275 }
276 
mspi_timing_config_psram_write_data(uint8_t * buf,uint32_t addr,uint32_t len)277 void mspi_timing_config_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
278 {
279     s_psram_execution(buf, addr, len, false);
280 }
281 
mspi_timing_config_psram_read_data(uint8_t * buf,uint32_t addr,uint32_t len)282 void mspi_timing_config_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
283 {
284     s_psram_execution(buf, addr, len, true);
285 }
286 
287 
288 /*-------------------------------------------------------------------------------------------------
289  * SPI1 Timing Tuning APIs
290  * These APIs are only used in `spi_flash_timing_tuning.c/sweep_for_success_sample_points()` for
291  * configuring SPI1 timing tuning related registers to find best tuning parameter
292  *-------------------------------------------------------------------------------------------------*/
mspi_timing_config_flash_set_tuning_regs(const mspi_timing_tuning_param_t * params)293 void mspi_timing_config_flash_set_tuning_regs(const mspi_timing_tuning_param_t *params)
294 {
295     /**
296      * 1. SPI_MEM_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless
297      *    SPI0 and SPI1 share the SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning
298      * 2. We use SPI1 to get the best Flash timing tuning (mode and num) config
299      */
300     mspi_timing_config_flash_set_din_mode_num(0, params->spi_din_mode, params->spi_din_num);
301     mspi_timing_config_flash_set_extra_dummy(1, params->extra_dummy_len);
302 }
303 
mspi_timing_config_psram_set_tuning_regs(const mspi_timing_tuning_param_t * params)304 void mspi_timing_config_psram_set_tuning_regs(const mspi_timing_tuning_param_t *params)
305 {
306     /**
307      * 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless
308      *    SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning
309      * 2. We use SPI1 to get the best PSRAM timing tuning (mode and num) config
310      */
311     mspi_timing_config_psram_set_din_mode_num(0, params->spi_din_mode, params->spi_din_num);
312 
313 #if CONFIG_SPIRAM_MODE_OCT
314     //On 728, for SPI1, flash and psram share the extra dummy register
315     mspi_timing_config_flash_set_extra_dummy(1, params->extra_dummy_len);
316 #elif CONFIG_SPIRAM_MODE_QUAD
317     //Update this `s_psram_extra_dummy`, the `s_psram_read_data` will set dummy according to this `s_psram_extra_dummy`
318     s_psram_extra_dummy = params->extra_dummy_len;
319     mspi_timing_ll_set_quad_flash_dummy(1, s_psram_extra_dummy - 1);
320 #endif
321 }
322 
323 #endif //#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
324 
325 
326 /*-------------------------------------------------------------------------------------------------
327  * To let upper lay (spi_flash_timing_tuning.c) to know the necessary timing registers
328  *-------------------------------------------------------------------------------------------------*/
329 /**
330  * Get the SPI1 Flash CS timing setting. The setup time and hold time are both realistic cycles.
331  * @note On ESP32-S3, SPI0/1 share the Flash CS timing registers. Therefore, we should not change these values.
332  * @note This function inform `spi_flash_timing_tuning.c` (driver layer) of the cycle,
333  * and other component (esp_flash driver) should get these cycle and configure the registers accordingly.
334  */
mspi_timing_config_get_cs_timing(uint8_t * setup_time,uint32_t * hold_time)335 void mspi_timing_config_get_cs_timing(uint8_t *setup_time, uint32_t *hold_time)
336 {
337     *setup_time = mspi_timing_ll_get_cs_setup_val(0);
338     *hold_time = mspi_timing_ll_get_cs_hold_val(0);
339     /**
340      * The logic here is, if setup_en / hold_en is false, then we return the realistic cycle number,
341      * which is 0. If true, then the realistic cycle number is (reg_value + 1)
342      */
343     if (mspi_timing_ll_is_cs_setup_enabled(0)) {
344         *setup_time += 1;
345     } else {
346         *setup_time = 0;
347     }
348     if (mspi_timing_ll_is_cs_hold_enabled(0)) {
349         *hold_time += 1;
350     } else {
351         *hold_time = 0;
352     }
353 }
354 
355 /**
356  * Get the SPI1 Flash clock setting.
357  * @note Similarly, this function inform `spi_flash_timing_tuning.c` (driver layer) of the clock setting,
358  * and other component (esp_flash driver) should get these and configure the registers accordingly.
359  */
mspi_timing_config_get_flash_clock_reg(void)360 uint32_t mspi_timing_config_get_flash_clock_reg(void)
361 {
362     return mspi_timing_ll_get_clock_reg(1);
363 }
364