Skip to content

Commit cc18192

Browse files
committed
Merge branch 'feat/ap_quad_psram_ecc_c61_c5' into 'master'
psram: add quad psram error correcting code (ECC) feature on ESP32C61/C5 Closes IDF-12027 See merge request espressif/esp-idf!36465
2 parents 94effc1 + 8a654ff commit cc18192

File tree

9 files changed

+669
-118
lines changed

9 files changed

+669
-118
lines changed

components/esp_psram/device/esp_psram_impl_ap_quad.c

Lines changed: 78 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -16,7 +16,7 @@
1616
#include "esp_private/mspi_timing_tuning.h"
1717
#include "esp_private/esp_gpio_reserve.h"
1818
#include "hal/psram_ctrlr_ll.h"
19-
#include "esp_quad_psram_defs.h"
19+
#include "esp_quad_psram_defs_ap.h"
2020
#include "soc/soc_caps.h"
2121

2222
static const char* TAG = "quad_psram";
@@ -31,7 +31,7 @@ uint8_t esp_psram_impl_get_cs_io(void)
3131
return s_psram_cs_io;
3232
}
3333

34-
void psram_exec_cmd(int spi_num, psram_hal_cmd_mode_t mode,
34+
void psram_exec_cmd(int spi_num, psram_cmd_mode_t mode,
3535
uint32_t cmd, int cmd_bit_len,
3636
uint32_t addr, int addr_bit_len,
3737
int dummy_bits,
@@ -60,7 +60,7 @@ void psram_exec_cmd(int spi_num, psram_hal_cmd_mode_t mode,
6060
static void psram_disable_qio_mode(int spi_num)
6161
{
6262
psram_exec_cmd(spi_num, PSRAM_HAL_CMD_QPI,
63-
PSRAM_EXIT_QMODE, 8, /* command and command bit len*/
63+
PSRAM_QUAD_EXIT_QMODE, 8, /* command and command bit len*/
6464
0, 0, /* address and address bit len*/
6565
0, /* dummy bit len */
6666
NULL, 0, /* tx data and tx bit len*/
@@ -72,10 +72,10 @@ static void psram_disable_qio_mode(int spi_num)
7272
//TODO IDF-4307
7373
//switch psram burst length(32 bytes or 1024 bytes)
7474
//datasheet says it should be 1024 bytes by default
75-
static void psram_set_wrap_burst_length(int spi_num, psram_hal_cmd_mode_t mode)
75+
static void psram_set_wrap_burst_length(int spi_num, psram_cmd_mode_t mode)
7676
{
7777
psram_exec_cmd(spi_num, mode,
78-
PSRAM_SET_BURST_LEN, 8, /* command and command bit len*/
78+
PSRAM_QUAD_SET_BURST_LEN, 8, /* command and command bit len*/
7979
0, 0, /* address and address bit len*/
8080
0, /* dummy bit len */
8181
NULL, 0, /* tx data and tx bit len*/
@@ -88,7 +88,7 @@ static void psram_set_wrap_burst_length(int spi_num, psram_hal_cmd_mode_t mode)
8888
static void psram_reset_mode(int spi_num)
8989
{
9090
psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI,
91-
PSRAM_RESET_EN, 8, /* command and command bit len*/
91+
PSRAM_QUAD_RESET_EN, 8, /* command and command bit len*/
9292
0, 0, /* address and address bit len*/
9393
0, /* dummy bit len */
9494
NULL, 0, /* tx data and tx bit len*/
@@ -97,7 +97,7 @@ static void psram_reset_mode(int spi_num)
9797
false); /* whether is program/erase operation */
9898

9999
psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI,
100-
PSRAM_RESET, 8, /* command and command bit len*/
100+
PSRAM_QUAD_RESET, 8, /* command and command bit len*/
101101
0, 0, /* address and address bit len*/
102102
0, /* dummy bit len */
103103
NULL, 0, /* tx data and tx bit len*/
@@ -144,7 +144,7 @@ bool psram_support_wrap_size(uint32_t wrap_size)
144144
static void psram_read_id(int spi_num, uint8_t* dev_id, int id_bits)
145145
{
146146
psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI,
147-
PSRAM_DEVICE_ID, 8, /* command and command bit len*/
147+
PSRAM_QUAD_DEVICE_ID, 8, /* command and command bit len*/
148148
0, 24, /* address and address bit len*/
149149
0, /* dummy bit len */
150150
NULL, 0, /* tx data and tx bit len*/
@@ -157,7 +157,7 @@ static void psram_read_id(int spi_num, uint8_t* dev_id, int id_bits)
157157
static void psram_enable_qio_mode(int spi_num)
158158
{
159159
psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI,
160-
PSRAM_ENTER_QMODE, 8, /* command and command bit len*/
160+
PSRAM_QUAD_ENTER_QMODE, 8, /* command and command bit len*/
161161
0, 0, /* address and address bit len*/
162162
0, /* dummy bit len */
163163
NULL, 0, /* tx data and tx bit len*/
@@ -168,14 +168,56 @@ static void psram_enable_qio_mode(int spi_num)
168168

169169
static void psram_set_cs_timing(void)
170170
{
171-
psram_ctrlr_ll_set_cs_hold(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CS_HOLD_VAL);
172-
psram_ctrlr_ll_set_cs_setup(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CS_SETUP_VAL);
171+
psram_ctrlr_ll_set_cs_hold(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CS_HOLD_VAL);
172+
psram_ctrlr_ll_set_cs_setup(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CS_SETUP_VAL);
173+
#if CONFIG_SPIRAM_ECC_ENABLE
174+
psram_ctrlr_ll_set_ecc_cs_hold(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CS_ECC_HOLD_TIME_VAL);
175+
#endif
173176
}
174177

178+
#if CONFIG_SPIRAM_ECC_ENABLE
179+
static void s_mspi_ecc_show_info(void)
180+
{
181+
for (int i = 0; i < PSRAM_CTRLR_LL_PMS_REGION_NUMS; i++) {
182+
ESP_EARLY_LOGV(TAG, "region[%d] addr: 0x%08x", i, psram_ctrlr_ll_get_pms_region_start_addr(PSRAM_CTRLR_LL_MSPI_ID_0, i));
183+
ESP_EARLY_LOGV(TAG, "region[%d] size: 0x%08x", i, psram_ctrlr_ll_get_pms_region_size(PSRAM_CTRLR_LL_MSPI_ID_0, i));
184+
}
185+
186+
uint32_t page_size = psram_ctrlr_ll_get_page_size(PSRAM_CTRLR_LL_MSPI_ID_0);
187+
ESP_EARLY_LOGV(TAG, "ECC page size: %d", page_size);
188+
}
189+
190+
/**
191+
* Enable error correcting code feature
192+
*
193+
* Can add an input parameter for selecting ECC mode if needed
194+
*/
195+
static void s_configure_psram_ecc(void)
196+
{
197+
psram_ctrlr_ll_set_ecc_mode(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_LL_ECC_MODE_16TO18);
198+
psram_ctrlr_ll_enable_skip_page_corner(PSRAM_CTRLR_LL_MSPI_ID_0, true);
199+
psram_ctrlr_ll_enable_split_trans(PSRAM_CTRLR_LL_MSPI_ID_0, true);
200+
psram_ctrlr_ll_set_page_size(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_PAGE_SIZE);
201+
psram_ctrlr_ll_enable_ecc_addr_conversion(PSRAM_CTRLR_LL_MSPI_ID_0, true);
202+
203+
/**
204+
* Enable ECC region 0 (ACE0)
205+
* Default: ACE0 range: 0 ~ 256MB
206+
* For current Quad PSRAM, ACE0 is enough
207+
*/
208+
psram_ctrlr_ll_set_pms_region_start_addr(PSRAM_CTRLR_LL_MSPI_ID_0, 0, 0);
209+
psram_ctrlr_ll_set_pms_region_size(PSRAM_CTRLR_LL_MSPI_ID_0, 0, 4096);
210+
psram_ctrlr_ll_set_pms_region_attr(PSRAM_CTRLR_LL_MSPI_ID_0, 0, PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE | PSRAM_CTRLR_LL_PMS_ATTR_READABLE);
211+
psram_ctrlr_ll_enable_pms_region_ecc(PSRAM_CTRLR_LL_MSPI_ID_0, 0, true);
212+
ESP_EARLY_LOGI(TAG, "ECC is enabled");
213+
s_mspi_ecc_show_info();
214+
}
215+
#endif
216+
175217
static void psram_gpio_config(void)
176218
{
177219
//CS1
178-
uint8_t cs1_io = PSRAM_CS_IO;
220+
uint8_t cs1_io = PSRAM_QUAD_CS_IO;
179221
if (cs1_io == MSPI_IOMUX_PIN_NUM_CS1) {
180222
gpio_ll_func_sel(&GPIO, cs1_io, FUNC_SPICS1_SPICS1);
181223
} else {
@@ -185,7 +227,7 @@ static void psram_gpio_config(void)
185227
s_psram_cs_io = cs1_io;
186228

187229
//WP HD
188-
uint8_t wp_io = PSRAM_SPIWP_SD3_IO;
230+
uint8_t wp_io = PSRAM_QUAD_SPIWP_SD3_IO;
189231
#if SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE
190232
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
191233
if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) {
@@ -224,7 +266,7 @@ static void s_config_psram_clock(void)
224266
bool s_check_aps3204_2tmode(void)
225267
{
226268
uint64_t full_eid = 0;
227-
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&full_eid, PSRAM_EID_BITS_NUM);
269+
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&full_eid, PSRAM_QUAD_EID_BITS_NUM);
228270

229271
bool is_2t = false;
230272
uint32_t eid_47_16 = __builtin_bswap32((full_eid >> 16) & UINT32_MAX);
@@ -240,6 +282,9 @@ esp_err_t esp_psram_impl_enable(void)
240282
{
241283
psram_gpio_config();
242284
psram_set_cs_timing();
285+
#if CONFIG_SPIRAM_ECC_ENABLE
286+
s_configure_psram_ecc();
287+
#endif
243288

244289
#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
245290
//enter MSPI slow mode to init PSRAM device registers
@@ -250,31 +295,31 @@ esp_err_t esp_psram_impl_enable(void)
250295

251296
//We use SPI1 to init PSRAM
252297
psram_disable_qio_mode(PSRAM_CTRLR_LL_MSPI_ID_1);
253-
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_ID_BITS_NUM);
254-
if (!PSRAM_IS_VALID(psram_id)) {
298+
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_QUAD_ID_BITS_NUM);
299+
if (!PSRAM_QUAD_IS_VALID(psram_id)) {
255300
/* 16Mbit psram ID read error workaround:
256301
* treat the first read id as a dummy one as the pre-condition,
257302
* Send Read ID command again
258303
*/
259-
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_ID_BITS_NUM);
260-
if (!PSRAM_IS_VALID(psram_id)) {
304+
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_QUAD_ID_BITS_NUM);
305+
if (!PSRAM_QUAD_IS_VALID(psram_id)) {
261306
ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x, PSRAM chip not found or not supported, or wrong PSRAM line mode", (uint32_t)psram_id);
262307
return ESP_ERR_NOT_SUPPORTED;
263308
}
264309
}
265310

266-
if (PSRAM_IS_64MBIT_TRIAL(psram_id)) {
311+
if (PSRAM_QUAD_IS_64MBIT_TRIAL(psram_id)) {
267312
s_psram_size = PSRAM_SIZE_8MB;
268313
} else {
269-
uint8_t density = PSRAM_SIZE_ID(psram_id);
270-
const int eid = PSRAM_EID_BIT_47_40(psram_id);
314+
uint8_t density = PSRAM_QUAD_SIZE_ID(psram_id);
315+
const int eid = PSRAM_QUAD_EID_BIT_47_40(psram_id);
271316
s_psram_size = density == 0x0 ? PSRAM_SIZE_2MB :
272317
density == 0x1 ? PSRAM_SIZE_4MB :
273318
density == 0x2 ? PSRAM_SIZE_8MB :
274319
/* Do not use `density` for QEMU PSRAM since we don't want any future QSPI PSRAM
275320
* that are 16MB or 32MB to be interpreted as QEMU PSRAM devices */
276-
eid == PSRAM_QEMU_16MB_ID ? PSRAM_SIZE_16MB :
277-
eid == PSRAM_QEMU_32MB_ID ? PSRAM_SIZE_32MB : 0;
321+
eid == PSRAM_QUAD_QEMU_16MB_ID ? PSRAM_SIZE_16MB :
322+
eid == PSRAM_QUAD_QEMU_32MB_ID ? PSRAM_SIZE_32MB : 0;
278323
}
279324

280325
if ((s_psram_size == PSRAM_SIZE_8MB) && s_check_aps3204_2tmode()) {
@@ -306,10 +351,10 @@ esp_err_t esp_psram_impl_enable(void)
306351
static void config_psram_spi_phases(void)
307352
{
308353
psram_ctrlr_ll_set_read_mode(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_HAL_CMD_QPI);
309-
psram_ctrlr_ll_set_wr_cmd(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CMD_LENGTH, PSRAM_QUAD_WRITE);
310-
psram_ctrlr_ll_set_rd_cmd(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CMD_LENGTH, PSRAM_FAST_READ_QUAD);
311-
psram_ctrlr_ll_set_addr_bitlen(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_ADDR_LENGTH);
312-
psram_ctrlr_ll_set_rd_dummy(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_FAST_READ_QUAD_DUMMY);
354+
psram_ctrlr_ll_set_wr_cmd(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CMD_LENGTH, PSRAM_QUAD_WRITE_QUAD);
355+
psram_ctrlr_ll_set_rd_cmd(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CMD_LENGTH, PSRAM_QUAD_FAST_READ_QUAD);
356+
psram_ctrlr_ll_set_addr_bitlen(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_ADDR_LENGTH);
357+
psram_ctrlr_ll_set_rd_dummy(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_FAST_READ_QUAD_DUMMY);
313358
psram_ctrlr_ll_set_cs_pin(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_LL_CS_ID_1);
314359
}
315360

@@ -330,16 +375,18 @@ esp_err_t esp_psram_impl_get_physical_size(uint32_t *out_size_bytes)
330375

331376
/**
332377
* This function is to get the available physical psram size in bytes.
333-
*
334-
* When ECC is enabled, the available size will be reduced.
335-
* On S3 Quad PSRAM, ECC is not enabled for now.
378+
* If ECC is enabled, available PSRAM size will be 7/8 times its physical size.
336379
*/
337380
esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes)
338381
{
339382
if (!out_size_bytes) {
340383
return ESP_ERR_INVALID_ARG;
341384
}
342385

386+
#if CONFIG_SPIRAM_ECC_ENABLE
387+
*out_size_bytes = s_psram_size * 7 / 8;
388+
#else
343389
*out_size_bytes = s_psram_size;
390+
#endif
344391
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
345392
}

components/esp_psram/device/esp_quad_psram_defs.h

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)