|
@@ -29,14 +29,28 @@
|
|
|
* 4. Some flash chips do nothing.
|
|
* 4. Some flash chips do nothing.
|
|
|
******************************************************************************/
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
-#if CONFIG_ESPTOOLPY_FLASHFREQ_120M
|
|
|
|
|
-#define FLASH_FREQUENCY 120
|
|
|
|
|
-#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M
|
|
|
|
|
-#define FLASH_FREQUENCY 80
|
|
|
|
|
-#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
|
|
|
|
|
-#define FLASH_FREQUENCY 40
|
|
|
|
|
-#elif CONFIG_ESPTOOLPY_FLASHFREQ_20M
|
|
|
|
|
-#define FLASH_FREQUENCY 20
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * Note: This file should only be compiled when HPM_ON, which is only available when !CONFIG_ESPTOOLPY_OCT_FLASH.
|
|
|
|
|
+ * However when HPM_ON, there are still some cases this file is not actually used:
|
|
|
|
|
+ *
|
|
|
|
|
+ * - !CONFIG_SPI_FLASH_UNDER_HIGH_FREQ:
|
|
|
|
|
+ * It mean that the flash not running under frequency requires HPM. spi_flash_enable_high_performance_mode() still
|
|
|
|
|
+ * called because caller shouldn't take care of the frequency.
|
|
|
|
|
+ *
|
|
|
|
|
+ * - bootloader_flash_is_octal_mode_enabled() == true:
|
|
|
|
|
+ * This is possible when `CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT` selected
|
|
|
|
|
+ *
|
|
|
|
|
+ * Octal Flash for now all support 120M. No need to enable HPM. The file is compiled, but will not actually run
|
|
|
|
|
+ * into spi_flash_enable_high_performance_mode().
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+void spi_flash_hpm_get_dummy_generic(spi_flash_hpm_dummy_conf_t *dummy_conf);
|
|
|
|
|
+
|
|
|
|
|
+#if CONFIG_SPI_FLASH_UNDER_HIGH_FREQ
|
|
|
|
|
+
|
|
|
|
|
+#if CONFIG_SPI_FLASH_HPM_AUTO
|
|
|
|
|
+// This only happens on S3, where HPM_AUTO leads to HPM_ON
|
|
|
|
|
+#warning High Performance Mode (QSPI Flash > 80MHz) is optional feature that depends on flash model. Read Docs First!
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
const static char *HPM_TAG = "flash HPM";
|
|
const static char *HPM_TAG = "flash HPM";
|
|
@@ -120,6 +134,7 @@ static esp_err_t spi_flash_high_performance_check_hpf_bit_5(void)
|
|
|
|
|
|
|
|
//-----------------For flash chips which enter HPM via adjust dummy-----------------------//
|
|
//-----------------For flash chips which enter HPM via adjust dummy-----------------------//
|
|
|
|
|
|
|
|
|
|
+#if CONFIG_SPI_FLASH_HPM_DC_ON
|
|
|
/**
|
|
/**
|
|
|
* @brief Probe the chip whether adjust dummy to enable HPM mode. Take XMC as an example:
|
|
* @brief Probe the chip whether adjust dummy to enable HPM mode. Take XMC as an example:
|
|
|
* Adjust dummy bits to enable HPM mode of the flash. If XMC works under 80MHz, the dummy bits
|
|
* Adjust dummy bits to enable HPM mode of the flash. If XMC works under 80MHz, the dummy bits
|
|
@@ -203,6 +218,14 @@ static void spi_flash_hpm_get_dummy_xmc(spi_flash_hpm_dummy_conf_t *dummy_conf)
|
|
|
dummy_conf->qout_dummy = SPI_FLASH_QOUT_DUMMY_BITLEN;
|
|
dummy_conf->qout_dummy = SPI_FLASH_QOUT_DUMMY_BITLEN;
|
|
|
dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
|
|
dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
|
|
|
}
|
|
}
|
|
|
|
|
+#elif !CONFIG_SPI_FLASH_HPM_DC_DISABLE
|
|
|
|
|
+
|
|
|
|
|
+//This is because bootloader doesn't support this
|
|
|
|
|
+#warning HPM-DC, which helps to run some flash > 80MHz by adjusting dummy cycles, is no longer enabled by default.
|
|
|
|
|
+#warning To enable this feature, your bootloader needs to have the support for it (by explicitly selecting BOOTLOADER_FLASH_DC_AWARE).
|
|
|
|
|
+#warning If your bootloader does not support it, select SPI_FLASH_HPM_DC_DISABLE to suppress the warning. READ DOCS FIRST!
|
|
|
|
|
+
|
|
|
|
|
+#endif //CONFIG_SPI_FLASH_HPM_DC_ON
|
|
|
|
|
|
|
|
//-----------------For flash chips which enter HPM via write status register-----------------------//
|
|
//-----------------For flash chips which enter HPM via write status register-----------------------//
|
|
|
|
|
|
|
@@ -284,25 +307,12 @@ static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_doi
|
|
|
return chip_cap;
|
|
return chip_cap;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-//-----------------------generic functions-------------------------------------//
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * @brief Default dummy for almost all flash chips. If your flash does't need to reconfigure dummy,
|
|
|
|
|
- * just call this function.
|
|
|
|
|
- */
|
|
|
|
|
-void __attribute__((weak)) spi_flash_hpm_get_dummy_generic(spi_flash_hpm_dummy_conf_t *dummy_conf)
|
|
|
|
|
-{
|
|
|
|
|
- dummy_conf->dio_dummy = SPI_FLASH_DIO_DUMMY_BITLEN;
|
|
|
|
|
- dummy_conf->dout_dummy = SPI_FLASH_DOUT_DUMMY_BITLEN;
|
|
|
|
|
- dummy_conf->qio_dummy = SPI_FLASH_QIO_DUMMY_BITLEN;
|
|
|
|
|
- dummy_conf->qout_dummy = SPI_FLASH_QOUT_DUMMY_BITLEN;
|
|
|
|
|
- dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[] = {
|
|
const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[] = {
|
|
|
/* vendor, chip_id, freq_threshold, temperature threshold, operation for setting high performance, reading HPF status, get dummy */
|
|
/* vendor, chip_id, freq_threshold, temperature threshold, operation for setting high performance, reading HPF status, get dummy */
|
|
|
{ "command", spi_flash_hpm_probe_chip_with_cmd, spi_flash_hpm_chip_hpm_requirement_check_with_cmd, spi_flash_enable_high_performance_send_cmd, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic },
|
|
{ "command", spi_flash_hpm_probe_chip_with_cmd, spi_flash_hpm_chip_hpm_requirement_check_with_cmd, spi_flash_enable_high_performance_send_cmd, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic },
|
|
|
|
|
+#if CONFIG_SPI_FLASH_HPM_DC_ON
|
|
|
{ "dummy", spi_flash_hpm_probe_chip_with_dummy, spi_flash_hpm_chip_hpm_requirement_check_with_dummy, spi_flash_turn_high_performance_reconfig_dummy, spi_flash_high_performance_check_dummy_sr, spi_flash_hpm_get_dummy_xmc},
|
|
{ "dummy", spi_flash_hpm_probe_chip_with_dummy, spi_flash_hpm_chip_hpm_requirement_check_with_dummy, spi_flash_turn_high_performance_reconfig_dummy, spi_flash_high_performance_check_dummy_sr, spi_flash_hpm_get_dummy_xmc},
|
|
|
|
|
+#endif //CONFIG_SPI_FLASH_HPM_DC_ON
|
|
|
{ "write sr3-bit5", spi_flash_hpm_probe_chip_with_write_hpf_bit_5, spi_flash_hpm_chip_hpm_requirement_check_with_write_hpf_bit_5, spi_flash_turn_high_performance_write_hpf_bit_5, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic},
|
|
{ "write sr3-bit5", spi_flash_hpm_probe_chip_with_write_hpf_bit_5, spi_flash_hpm_chip_hpm_requirement_check_with_write_hpf_bit_5, spi_flash_turn_high_performance_write_hpf_bit_5, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic},
|
|
|
{ "noting-to-do", spi_flash_hpm_probe_chip_with_doing_nothing, spi_flash_hpm_chip_hpm_requirement_check_with_doing_nothing, NULL, NULL, spi_flash_hpm_get_dummy_generic},
|
|
{ "noting-to-do", spi_flash_hpm_probe_chip_with_doing_nothing, spi_flash_hpm_chip_hpm_requirement_check_with_doing_nothing, NULL, NULL, spi_flash_hpm_get_dummy_generic},
|
|
|
// default: do nothing, but keep the dummy get function. The first item with NULL as its probe will be the fallback.
|
|
// default: do nothing, but keep the dummy get function. The first item with NULL as its probe will be the fallback.
|
|
@@ -310,8 +320,26 @@ const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[] = {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const spi_flash_hpm_info_t *chip_hpm = NULL;
|
|
static const spi_flash_hpm_info_t *chip_hpm = NULL;
|
|
|
-static spi_flash_hpm_dummy_conf_t dummy_conf;
|
|
|
|
|
-static bool hpm_dummy_changed = false;
|
|
|
|
|
|
|
+
|
|
|
|
|
+#if CONFIG_SPI_FLASH_HPM_DC_ON
|
|
|
|
|
+static bool s_hpm_dummy_changed = false;
|
|
|
|
|
+static spi_flash_hpm_dummy_conf_t s_dummy_conf;
|
|
|
|
|
+
|
|
|
|
|
+const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void)
|
|
|
|
|
+{
|
|
|
|
|
+ chip_hpm->flash_get_dummy(&s_dummy_conf);
|
|
|
|
|
+ return &s_dummy_conf;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool spi_flash_hpm_dummy_adjust(void)
|
|
|
|
|
+{
|
|
|
|
|
+ return s_hpm_dummy_changed;
|
|
|
|
|
+}
|
|
|
|
|
+#endif //CONFIG_SPI_FLASH_HPM_DC_ON
|
|
|
|
|
+
|
|
|
|
|
+#if CONFIG_ESPTOOLPY_FLASHFREQ_120M
|
|
|
|
|
+#define FLASH_FREQUENCY 120
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
esp_err_t spi_flash_enable_high_performance_mode(void)
|
|
esp_err_t spi_flash_enable_high_performance_mode(void)
|
|
|
{
|
|
{
|
|
@@ -322,6 +350,21 @@ esp_err_t spi_flash_enable_high_performance_mode(void)
|
|
|
int voltage = 0;
|
|
int voltage = 0;
|
|
|
int temperature = 0;
|
|
int temperature = 0;
|
|
|
|
|
|
|
|
|
|
+#if CONFIG_SPI_FLASH_HPM_AUTO
|
|
|
|
|
+ ESP_EARLY_LOGW(HPM_TAG, "HPM mode is optional feature that depends on flash model. Read Docs First!");
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#if CONFIG_SPI_FLASH_HPM_DC_DISABLE
|
|
|
|
|
+ // case 1: force disabled
|
|
|
|
|
+ ESP_EARLY_LOGI(HPM_TAG, "w/o HPM-DC support");
|
|
|
|
|
+#elif CONFIG_SPI_FLASH_HPM_DC_ON
|
|
|
|
|
+ // case 2: auto, and actually enabled
|
|
|
|
|
+ ESP_EARLY_LOGI(HPM_TAG, "with HPM-DC support");
|
|
|
|
|
+#else
|
|
|
|
|
+ // case 3: auto, but disabled (not supported by bootloader)
|
|
|
|
|
+ ESP_EARLY_LOGW(HPM_TAG, "HPM mode with DC adjustment is disabled. Some flash models may not be supported. Read Docs First!");
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
const spi_flash_hpm_info_t *chip = spi_flash_hpm_enable_list;
|
|
const spi_flash_hpm_info_t *chip = spi_flash_hpm_enable_list;
|
|
|
esp_err_t ret = ESP_OK;
|
|
esp_err_t ret = ESP_OK;
|
|
|
while (chip->probe) {
|
|
while (chip->probe) {
|
|
@@ -333,10 +376,12 @@ esp_err_t spi_flash_enable_high_performance_mode(void)
|
|
|
}
|
|
}
|
|
|
chip_hpm = chip;
|
|
chip_hpm = chip;
|
|
|
|
|
|
|
|
|
|
+ /* When > 80 MHz, flash chips usually need special HPM support to run normally. The support is chip-specific. When
|
|
|
|
|
+ * the chip is not in the known flash list, nothing will be done and there will be an warning.
|
|
|
|
|
+ * When <= 80 MHz, it's assumed that all flash chips can run without chip-specific HPM support. This function will not be called and there will be no warning.
|
|
|
|
|
+ */
|
|
|
if (ret != ESP_OK) {
|
|
if (ret != ESP_OK) {
|
|
|
-#if (FLASH_FREQUENCY == 120)
|
|
|
|
|
- ESP_EARLY_LOGW(HPM_TAG, "Flash high performance mode hasn't been supported");
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
+ ESP_EARLY_LOGW(HPM_TAG, "High performance mode of this flash model hasn't been supported.");
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -350,21 +395,50 @@ esp_err_t spi_flash_enable_high_performance_mode(void)
|
|
|
ESP_EARLY_LOGE(HPM_TAG, "Flash high performance mode hasn't been executed successfully");
|
|
ESP_EARLY_LOGE(HPM_TAG, "Flash high performance mode hasn't been executed successfully");
|
|
|
return ESP_FAIL;
|
|
return ESP_FAIL;
|
|
|
}
|
|
}
|
|
|
- hpm_dummy_changed = (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED) ? true : false;
|
|
|
|
|
|
|
+#if CONFIG_SPI_FLASH_HPM_DC_ON
|
|
|
|
|
+ s_hpm_dummy_changed = (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED) ? true : false;
|
|
|
|
|
+#else
|
|
|
|
|
+ assert(hpm_requirement_check != SPI_FLASH_HPM_DUMMY_NEEDED);
|
|
|
|
|
+#endif
|
|
|
} else if (hpm_requirement_check == SPI_FLASH_HPM_BEYOND_LIMIT) {
|
|
} else if (hpm_requirement_check == SPI_FLASH_HPM_BEYOND_LIMIT) {
|
|
|
ESP_EARLY_LOGE(HPM_TAG, "Flash does not have the ability to raise to that frequency");
|
|
ESP_EARLY_LOGE(HPM_TAG, "Flash does not have the ability to raise to that frequency");
|
|
|
return ESP_FAIL;
|
|
return ESP_FAIL;
|
|
|
}
|
|
}
|
|
|
return ESP_OK;
|
|
return ESP_OK;
|
|
|
}
|
|
}
|
|
|
|
|
+#else
|
|
|
|
|
+//!CONFIG_SPI_FLASH_UNDER_HIGH_FREQ
|
|
|
|
|
+
|
|
|
|
|
+static spi_flash_hpm_dummy_conf_t s_dummy_conf;
|
|
|
|
|
+
|
|
|
|
|
+esp_err_t spi_flash_enable_high_performance_mode(void)
|
|
|
|
|
+{
|
|
|
|
|
+ return ESP_OK;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void)
|
|
const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void)
|
|
|
{
|
|
{
|
|
|
- chip_hpm->flash_get_dummy(&dummy_conf);
|
|
|
|
|
- return &dummy_conf;
|
|
|
|
|
|
|
+ spi_flash_hpm_get_dummy_generic(&s_dummy_conf);
|
|
|
|
|
+ return &s_dummy_conf;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool spi_flash_hpm_dummy_adjust(void)
|
|
bool spi_flash_hpm_dummy_adjust(void)
|
|
|
{
|
|
{
|
|
|
- return hpm_dummy_changed;
|
|
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+#endif //CONFIG_SPI_FLASH_UNDER_HIGH_FREQ
|
|
|
|
|
+
|
|
|
|
|
+//-----------------------generic functions-------------------------------------//
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @brief Default dummy for almost all flash chips. If your flash does't need to reconfigure dummy,
|
|
|
|
|
+ * just call this function.
|
|
|
|
|
+ */
|
|
|
|
|
+void __attribute__((weak)) spi_flash_hpm_get_dummy_generic(spi_flash_hpm_dummy_conf_t *dummy_conf)
|
|
|
|
|
+{
|
|
|
|
|
+ dummy_conf->dio_dummy = SPI_FLASH_DIO_DUMMY_BITLEN;
|
|
|
|
|
+ dummy_conf->dout_dummy = SPI_FLASH_DOUT_DUMMY_BITLEN;
|
|
|
|
|
+ dummy_conf->qio_dummy = SPI_FLASH_QIO_DUMMY_BITLEN;
|
|
|
|
|
+ dummy_conf->qout_dummy = SPI_FLASH_QOUT_DUMMY_BITLEN;
|
|
|
|
|
+ dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
|
|
|
}
|
|
}
|