mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
feat(psram): support fallback to use default driver pattern when id isn't match
This commit is contained in:
@@ -48,7 +48,8 @@
|
|||||||
#define AP_HEX_PSRAM_WR_LATENCY 2
|
#define AP_HEX_PSRAM_WR_LATENCY 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define AP_HEX_PSRAM_VENDOR_ID 0xD
|
#define AP_HEX_PSRAM_VENDOR_ID_AP 0xD
|
||||||
|
#define AP_HEX_PSRAM_VENDOR_ID_UNILC 0x1A //UnilC shares driver pattern with AP
|
||||||
#define AP_HEX_PSRAM_CS_SETUP_TIME 4
|
#define AP_HEX_PSRAM_CS_SETUP_TIME 4
|
||||||
#define AP_HEX_PSRAM_CS_HOLD_TIME 4
|
#define AP_HEX_PSRAM_CS_HOLD_TIME 4
|
||||||
#define AP_HEX_PSRAM_CS_ECC_HOLD_TIME 4
|
#define AP_HEX_PSRAM_CS_ECC_HOLD_TIME 4
|
||||||
@@ -60,6 +61,8 @@
|
|||||||
#define AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ 400
|
#define AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ 400
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define AP_HEX_PSRAM_REF_DATA 0x5a6b7c8d
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@@ -261,6 +264,41 @@ static void s_get_psram_mode_reg(int spi_num, hex_psram_mode_reg_t *out_reg)
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if PSRAM is connected by write and read
|
||||||
|
*/
|
||||||
|
static esp_err_t s_check_psram_connected(int spi_num)
|
||||||
|
{
|
||||||
|
uint32_t addr = 0x80;
|
||||||
|
uint32_t ref_data = AP_HEX_PSRAM_REF_DATA;
|
||||||
|
uint32_t exp_data = 0;
|
||||||
|
int data_bit_len = 32;
|
||||||
|
|
||||||
|
//write
|
||||||
|
addr = 0x0;
|
||||||
|
s_psram_common_transaction(spi_num,
|
||||||
|
AP_HEX_PSRAM_SYNC_WRITE, AP_HEX_PSRAM_WR_CMD_BITLEN,
|
||||||
|
addr, AP_HEX_PSRAM_ADDR_BITLEN,
|
||||||
|
AP_HEX_PSRAM_WR_DUMMY_BITLEN,
|
||||||
|
(uint8_t *)&ref_data, data_bit_len,
|
||||||
|
NULL, 0,
|
||||||
|
false);
|
||||||
|
|
||||||
|
//read MR4 and MR8
|
||||||
|
s_psram_common_transaction(spi_num,
|
||||||
|
AP_HEX_PSRAM_SYNC_READ, AP_HEX_PSRAM_RD_CMD_BITLEN,
|
||||||
|
addr, AP_HEX_PSRAM_ADDR_BITLEN,
|
||||||
|
AP_HEX_PSRAM_RD_DUMMY_BITLEN,
|
||||||
|
NULL, 0,
|
||||||
|
(uint8_t *)&exp_data, data_bit_len,
|
||||||
|
false);
|
||||||
|
|
||||||
|
ESP_EARLY_LOGD(TAG, "exp_data: 0x%08x", exp_data);
|
||||||
|
ESP_EARLY_LOGD(TAG, "ref_data: 0x%08x", ref_data);
|
||||||
|
|
||||||
|
return (exp_data == ref_data ? ESP_OK : ESP_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
static void s_print_psram_info(hex_psram_mode_reg_t *reg_val)
|
static void s_print_psram_info(hex_psram_mode_reg_t *reg_val)
|
||||||
{
|
{
|
||||||
ESP_EARLY_LOGI(TAG, "vendor id : 0x%02x (%s)", reg_val->mr1.vendor_id, reg_val->mr1.vendor_id == 0x0d ? "AP" : "UNKNOWN");
|
ESP_EARLY_LOGI(TAG, "vendor id : 0x%02x (%s)", reg_val->mr1.vendor_id, reg_val->mr1.vendor_id == 0x0d ? "AP" : "UNKNOWN");
|
||||||
@@ -411,12 +449,17 @@ esp_err_t esp_psram_impl_enable(void)
|
|||||||
mode_reg.mr8.x16 = 0;
|
mode_reg.mr8.x16 = 0;
|
||||||
#endif
|
#endif
|
||||||
s_init_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg);
|
s_init_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg);
|
||||||
//Print PSRAM info
|
|
||||||
s_get_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg);
|
if (s_check_psram_connected(PSRAM_CTRLR_LL_MSPI_ID_3) != ESP_OK) {
|
||||||
if (mode_reg.mr1.vendor_id != AP_HEX_PSRAM_VENDOR_ID) {
|
ESP_EARLY_LOGE(TAG, "PSRAM chip is not connected");
|
||||||
ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x, PSRAM chip not found or not supported, or wrong PSRAM line mode", mode_reg.mr1.vendor_id);
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_get_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg);
|
||||||
|
if (mode_reg.mr1.vendor_id != AP_HEX_PSRAM_VENDOR_ID_AP && mode_reg.mr1.vendor_id != AP_HEX_PSRAM_VENDOR_ID_UNILC) {
|
||||||
|
ESP_EARLY_LOGW(TAG, "PSRAM ID read error: 0x%08x, fallback to use default driver pattern", mode_reg.mr1.vendor_id);
|
||||||
|
}
|
||||||
|
|
||||||
s_print_psram_info(&mode_reg);
|
s_print_psram_info(&mode_reg);
|
||||||
s_psram_size = mode_reg.mr2.density == 0x1 ? PSRAM_SIZE_4MB :
|
s_psram_size = mode_reg.mr2.density == 0x1 ? PSRAM_SIZE_4MB :
|
||||||
mode_reg.mr2.density == 0X3 ? PSRAM_SIZE_8MB :
|
mode_reg.mr2.density == 0X3 ? PSRAM_SIZE_8MB :
|
||||||
|
@@ -19,6 +19,8 @@
|
|||||||
#include "esp_quad_psram_defs_ap.h"
|
#include "esp_quad_psram_defs_ap.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
|
#define AP_HEX_PSRAM_REF_DATA 0x5a6b7c8d
|
||||||
|
|
||||||
static const char* TAG = "quad_psram";
|
static const char* TAG = "quad_psram";
|
||||||
|
|
||||||
static uint32_t s_psram_size = 0; //this stands for physical psram size in bytes
|
static uint32_t s_psram_size = 0; //this stands for physical psram size in bytes
|
||||||
@@ -175,6 +177,42 @@ static void psram_set_cs_timing(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if PSRAM is connected by write and read
|
||||||
|
*/
|
||||||
|
static esp_err_t s_check_psram_connected(int spi_num)
|
||||||
|
{
|
||||||
|
uint32_t addr = 0x0;
|
||||||
|
uint32_t ref_data = AP_HEX_PSRAM_REF_DATA;
|
||||||
|
uint32_t exp_data = 0;
|
||||||
|
int data_bit_len = 32;
|
||||||
|
|
||||||
|
//write
|
||||||
|
psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI,
|
||||||
|
PSRAM_QUAD_WRITE, PSRAM_QUAD_CMD_LENGTH,
|
||||||
|
addr, PSRAM_QUAD_ADDR_LENGTH,
|
||||||
|
0,
|
||||||
|
(uint8_t *)&ref_data, data_bit_len,
|
||||||
|
NULL, 0,
|
||||||
|
PSRAM_LL_CS_SEL,
|
||||||
|
false);
|
||||||
|
|
||||||
|
//read MR4 and MR8
|
||||||
|
psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI,
|
||||||
|
PSRAM_QUAD_READ, PSRAM_QUAD_CMD_LENGTH,
|
||||||
|
addr, PSRAM_QUAD_ADDR_LENGTH,
|
||||||
|
0,
|
||||||
|
NULL, 0,
|
||||||
|
(uint8_t *)&exp_data, data_bit_len,
|
||||||
|
PSRAM_LL_CS_SEL,
|
||||||
|
false);
|
||||||
|
|
||||||
|
ESP_EARLY_LOGW(TAG, "exp_data: 0x%08x", exp_data);
|
||||||
|
ESP_EARLY_LOGW(TAG, "ref_data: 0x%08x", ref_data);
|
||||||
|
|
||||||
|
return (exp_data == ref_data ? ESP_OK : ESP_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_ECC_ENABLE
|
#if CONFIG_SPIRAM_ECC_ENABLE
|
||||||
static void s_mspi_ecc_show_info(void)
|
static void s_mspi_ecc_show_info(void)
|
||||||
{
|
{
|
||||||
@@ -319,6 +357,12 @@ esp_err_t esp_psram_impl_enable(void)
|
|||||||
|
|
||||||
//We use SPI1 to init PSRAM
|
//We use SPI1 to init PSRAM
|
||||||
psram_disable_qio_mode(PSRAM_CTRLR_LL_MSPI_ID_1);
|
psram_disable_qio_mode(PSRAM_CTRLR_LL_MSPI_ID_1);
|
||||||
|
|
||||||
|
if (s_check_psram_connected(PSRAM_CTRLR_LL_MSPI_ID_1) != ESP_OK) {
|
||||||
|
ESP_EARLY_LOGE(TAG, "PSRAM chip is not connected, or wrong PSRAM line mode");
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_QUAD_ID_BITS_NUM);
|
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_QUAD_ID_BITS_NUM);
|
||||||
if (!PSRAM_QUAD_IS_VALID(psram_id)) {
|
if (!PSRAM_QUAD_IS_VALID(psram_id)) {
|
||||||
/* 16Mbit psram ID read error workaround:
|
/* 16Mbit psram ID read error workaround:
|
||||||
@@ -327,8 +371,7 @@ esp_err_t esp_psram_impl_enable(void)
|
|||||||
*/
|
*/
|
||||||
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_QUAD_ID_BITS_NUM);
|
psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_QUAD_ID_BITS_NUM);
|
||||||
if (!PSRAM_QUAD_IS_VALID(psram_id)) {
|
if (!PSRAM_QUAD_IS_VALID(psram_id)) {
|
||||||
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);
|
ESP_EARLY_LOGW(TAG, "PSRAM ID read error: 0x%08x, fallback to use default driver pattern", (uint32_t)psram_id);
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ESP_EARLY_LOGV(TAG, "MFID: 0x%x", PSRAM_QUAD_MFID(psram_id));
|
ESP_EARLY_LOGV(TAG, "MFID: 0x%x", PSRAM_QUAD_MFID(psram_id));
|
||||||
|
@@ -45,6 +45,8 @@
|
|||||||
#define OCT_PSRAM_PAGE_SIZE 2 //2 for 1024B
|
#define OCT_PSRAM_PAGE_SIZE 2 //2 for 1024B
|
||||||
#define OCT_PSRAM_ECC_ENABLE_MASK BIT(8)
|
#define OCT_PSRAM_ECC_ENABLE_MASK BIT(8)
|
||||||
|
|
||||||
|
#define OCT_PSRAM_REF_DATA 0x5a6b7c8d
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@@ -222,6 +224,44 @@ static void s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *out_reg)
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if PSRAM is connected by write and read
|
||||||
|
*/
|
||||||
|
static esp_err_t s_check_psram_connected(int spi_num)
|
||||||
|
{
|
||||||
|
esp_rom_spiflash_read_mode_t mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
|
||||||
|
int cmd_len = OCT_PSRAM_WR_CMD_BITLEN;
|
||||||
|
uint32_t addr = 0x0;
|
||||||
|
int addr_bit_len = OCT_PSRAM_ADDR_BITLEN;
|
||||||
|
uint32_t ref_data = OCT_PSRAM_REF_DATA;
|
||||||
|
uint32_t exp_data = 0;
|
||||||
|
int data_bit_len = 32;
|
||||||
|
|
||||||
|
//write
|
||||||
|
esp_rom_opiflash_exec_cmd(spi_num, mode,
|
||||||
|
OPI_PSRAM_SYNC_WRITE, cmd_len,
|
||||||
|
addr, addr_bit_len,
|
||||||
|
OCT_PSRAM_WR_DUMMY_BITLEN,
|
||||||
|
(uint8_t *)&ref_data, data_bit_len,
|
||||||
|
NULL, 0,
|
||||||
|
BIT(1),
|
||||||
|
false);
|
||||||
|
//read
|
||||||
|
esp_rom_opiflash_exec_cmd(spi_num, mode,
|
||||||
|
OPI_PSRAM_SYNC_READ, cmd_len,
|
||||||
|
addr, addr_bit_len,
|
||||||
|
OCT_PSRAM_RD_DUMMY_BITLEN,
|
||||||
|
NULL, 0,
|
||||||
|
(uint8_t *)&exp_data, data_bit_len,
|
||||||
|
BIT(1),
|
||||||
|
false);
|
||||||
|
|
||||||
|
ESP_EARLY_LOGD(TAG, "exp_data: 0x%08x", exp_data);
|
||||||
|
ESP_EARLY_LOGD(TAG, "ref_data: 0x%08x", ref_data);
|
||||||
|
|
||||||
|
return (exp_data == ref_data ? ESP_OK : ESP_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
static void s_print_psram_info(opi_psram_mode_reg_t *reg_val)
|
static void s_print_psram_info(opi_psram_mode_reg_t *reg_val)
|
||||||
{
|
{
|
||||||
ESP_EARLY_LOGI(TAG, "vendor id : 0x%02x (%s)", reg_val->mr1.vendor_id, reg_val->mr1.vendor_id == 0x0d ? "AP" : (reg_val->mr1.vendor_id == 0x1a ? "UnilC" : "UNKNOWN"));
|
ESP_EARLY_LOGI(TAG, "vendor id : 0x%02x (%s)", reg_val->mr1.vendor_id, reg_val->mr1.vendor_id == 0x0d ? "AP" : (reg_val->mr1.vendor_id == 0x1a ? "UnilC" : "UNKNOWN"));
|
||||||
@@ -316,12 +356,17 @@ esp_err_t esp_psram_impl_enable(void)
|
|||||||
mode_reg.mr8.bl = 3;
|
mode_reg.mr8.bl = 3;
|
||||||
mode_reg.mr8.bt = 0;
|
mode_reg.mr8.bt = 0;
|
||||||
s_init_psram_mode_reg(1, &mode_reg);
|
s_init_psram_mode_reg(1, &mode_reg);
|
||||||
//Print PSRAM info
|
|
||||||
s_get_psram_mode_reg(1, &mode_reg);
|
if (s_check_psram_connected(1) != ESP_OK) {
|
||||||
if (mode_reg.mr1.vendor_id != OCT_PSRAM_VENDOR_ID_AP && mode_reg.mr1.vendor_id != OCT_PSRAM_VENDOR_ID_UNILC) {
|
ESP_EARLY_LOGE(TAG, "PSRAM chip is not connected, or wrong PSRAM line mode");
|
||||||
ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x, PSRAM chip not found or not supported, or wrong PSRAM line mode", mode_reg.mr1.vendor_id);
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_get_psram_mode_reg(1, &mode_reg);
|
||||||
|
if (mode_reg.mr1.vendor_id != OCT_PSRAM_VENDOR_ID_AP && mode_reg.mr1.vendor_id != OCT_PSRAM_VENDOR_ID_UNILC) {
|
||||||
|
ESP_EARLY_LOGW(TAG, "PSRAM ID read error: 0x%08x, fallback to use default driver pattern", mode_reg.mr1.vendor_id);
|
||||||
|
}
|
||||||
|
|
||||||
s_print_psram_info(&mode_reg);
|
s_print_psram_info(&mode_reg);
|
||||||
s_psram_size = mode_reg.mr2.density == 0x1 ? PSRAM_SIZE_4MB :
|
s_psram_size = mode_reg.mr2.density == 0x1 ? PSRAM_SIZE_4MB :
|
||||||
mode_reg.mr2.density == 0X3 ? PSRAM_SIZE_8MB :
|
mode_reg.mr2.density == 0X3 ? PSRAM_SIZE_8MB :
|
||||||
|
Reference in New Issue
Block a user