+
+#if defined(CONFIG_ENV_SPI_EARLY)
+/*
+ * early load environment from SPI flash (before relocation)
+ * and check if it is valid.
+ */
+static int env_sf_init_early(void)
+{
+ int ret;
+ int read1_fail;
+ int read2_fail;
+ int crc1_ok;
+ env_t *tmp_env2 = NULL;
+ env_t *tmp_env1;
+ struct spi_flash *env_flash;
+
+ /*
+ * if malloc is not ready yet, we cannot use
+ * this part yet.
+ */
+ if (!gd->malloc_limit)
+ return -ENOENT;
+
+ tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN,
+ CONFIG_ENV_SIZE);
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
+ tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN,
+ CONFIG_ENV_SIZE);
+
+ if (!tmp_env1 || !tmp_env2)
+ goto out;
+
+ ret = setup_flash_device(&env_flash);
+ if (ret)
+ goto out;
+
+ read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
+ CONFIG_ENV_SIZE, tmp_env1);
+
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) {
+ read2_fail = spi_flash_read(env_flash,
+ CONFIG_ENV_OFFSET_REDUND,
+ CONFIG_ENV_SIZE, tmp_env2);
+ ret = env_check_redund((char *)tmp_env1, read1_fail,
+ (char *)tmp_env2, read2_fail);
+
+ if (ret < 0)
+ goto err_read;
+
+ if (gd->env_valid == ENV_VALID)
+ gd->env_addr = (unsigned long)&tmp_env1->data;
+ else
+ gd->env_addr = (unsigned long)&tmp_env2->data;
+ } else {
+ if (read1_fail)
+ goto err_read;
+
+ crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) ==
+ tmp_env1->crc;
+ if (!crc1_ok)
+ goto err_read;
+
+ /* if valid -> this is our env */
+ gd->env_valid = ENV_VALID;
+ gd->env_addr = (unsigned long)&tmp_env1->data;
+ }
+
+ spi_flash_free(env_flash);
+
+ return 0;
+err_read:
+ spi_flash_free(env_flash);
+
+ free(tmp_env1);
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
+ free(tmp_env2);
+out:
+ /* env is not valid. always return 0 */
+ gd->env_valid = ENV_INVALID;
+ return 0;
+}
+#endif
+
+static int env_sf_init(void)
+{
+ int ret = env_sf_init_addr();
+ if (ret != -ENOENT)
+ return ret;
+#ifdef CONFIG_ENV_SPI_EARLY
+ return env_sf_init_early();