blob: 06cc62e005c67c3f5643557a4b9390acd9dec831 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Haavard Skinnemoen8c664972008-05-16 11:10:35 +02002/*
Wolfgang Denkea882ba2010-06-20 23:33:59 +02003 * (C) Copyright 2000-2010
Haavard Skinnemoen8c664972008-05-16 11:10:35 +02004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 *
6 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7 * Andreas Heppel <aheppel@sysgo.de>
8 *
9 * (C) Copyright 2008 Atmel Corporation
Haavard Skinnemoen8c664972008-05-16 11:10:35 +020010 */
11#include <common.h>
Simon Glass9d922452017-05-17 17:18:03 -060012#include <dm.h>
Simon Glass0ac7d722019-08-01 09:47:00 -060013#include <env.h>
Simon Glassf3998fd2019-08-02 09:44:25 -060014#include <env_internal.h>
Simon Glassb79fdc72020-05-10 11:39:54 -060015#include <flash.h>
Mike Frysinger5b3375a2008-12-11 06:23:37 -050016#include <malloc.h>
Simon Glass843c9e82014-10-13 23:41:55 -060017#include <spi.h>
Haavard Skinnemoen8c664972008-05-16 11:10:35 +020018#include <spi_flash.h>
Wolfgang Denkea882ba2010-06-20 23:33:59 +020019#include <search.h>
20#include <errno.h>
Simon Glassb79fdc72020-05-10 11:39:54 -060021#include <uuid.h>
Simon Glass90526e92020-05-10 11:39:56 -060022#include <asm/cache.h>
Simon Glass401d1c42020-10-30 21:38:53 -060023#include <asm/global_data.h>
Gong Qianyu19c31282016-01-26 15:06:42 +080024#include <dm/device-internal.h>
Simon Glass3db71102019-11-14 12:57:16 -070025#include <u-boot/crc.h>
Haavard Skinnemoen8c664972008-05-16 11:10:35 +020026
Simon Glass4415f1d2017-08-03 12:21:58 -060027#ifndef CONFIG_SPL_BUILD
Ashish Kumarb500c922017-12-14 17:37:08 +053028#define INITENV
Simon Glass4415f1d2017-08-03 12:21:58 -060029#endif
30
Wolfgang Wegner7319bca2010-04-23 17:22:55 +020031#ifdef CONFIG_ENV_OFFSET_REDUND
Igor Grinbergeb58a7f2011-11-07 01:14:08 +000032static ulong env_offset = CONFIG_ENV_OFFSET;
33static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND;
Stefano Babica3110f02010-10-27 11:06:20 +020034#endif /* CONFIG_ENV_OFFSET_REDUND */
Wolfgang Wegner7319bca2010-04-23 17:22:55 +020035
Haavard Skinnemoen8c664972008-05-16 11:10:35 +020036DECLARE_GLOBAL_DATA_PTR;
37
Haavard Skinnemoen8c664972008-05-16 11:10:35 +020038static struct spi_flash *env_flash;
39
Andreas Fenkartafa81a72017-04-08 11:59:31 +020040static int setup_flash_device(void)
Wolfgang Wegner7319bca2010-04-23 17:22:55 +020041{
Lukasz Majewski56c40462020-06-04 23:11:53 +080042#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
Gong Qianyu19c31282016-01-26 15:06:42 +080043 struct udevice *new;
Andreas Fenkartafa81a72017-04-08 11:59:31 +020044 int ret;
Gong Qianyu19c31282016-01-26 15:06:42 +080045
Vignesh R96907c02016-07-06 10:04:28 +053046 /* speed and mode will be read from DT */
Gong Qianyu19c31282016-01-26 15:06:42 +080047 ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
Konstantin Porotchkin25a17652018-08-29 16:34:52 +030048 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE,
49 &new);
Gong Qianyu19c31282016-01-26 15:06:42 +080050 if (ret) {
Simon Glass0ac7d722019-08-01 09:47:00 -060051 env_set_default("spi_flash_probe_bus_cs() failed", 0);
Simon Glassc5951992017-08-03 12:22:17 -060052 return ret;
Gong Qianyu19c31282016-01-26 15:06:42 +080053 }
54
55 env_flash = dev_get_uclass_priv(new);
56#else
Jagan Tekic8cbf172020-05-13 16:32:42 +053057 if (env_flash)
58 spi_flash_free(env_flash);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +020059
Jagan Tekic8cbf172020-05-13 16:32:42 +053060 env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
61 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +020062 if (!env_flash) {
Jagan Tekic8cbf172020-05-13 16:32:42 +053063 env_set_default("spi_flash_probe() failed", 0);
64 return -EIO;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +020065 }
Gong Qianyu19c31282016-01-26 15:06:42 +080066#endif
Andreas Fenkartafa81a72017-04-08 11:59:31 +020067 return 0;
68}
69
70#if defined(CONFIG_ENV_OFFSET_REDUND)
Simon Glasse5bce242017-08-03 12:22:01 -060071static int env_sf_save(void)
Andreas Fenkartafa81a72017-04-08 11:59:31 +020072{
73 env_t env_new;
Simon Glassd3716dd2019-08-01 09:47:08 -060074 char *saved_buffer = NULL, flag = ENV_REDUND_OBSOLETE;
Rasmus Villemoesbcb44f62021-04-14 20:51:43 +020075 u32 saved_size = 0, saved_offset = 0, sector;
Rasmus Villemoes4da73472021-04-14 20:51:42 +020076 u32 sect_size = CONFIG_ENV_SECT_SIZE;
Andreas Fenkartafa81a72017-04-08 11:59:31 +020077 int ret;
78
79 ret = setup_flash_device();
80 if (ret)
81 return ret;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +020082
Rasmus Villemoesbcb44f62021-04-14 20:51:43 +020083 if (IS_ENABLED(CONFIG_ENV_SECT_SIZE_AUTO))
84 sect_size = env_flash->mtd.erasesize;
85
Marek Vasut7ce15262014-03-05 19:59:50 +010086 ret = env_export(&env_new);
87 if (ret)
Simon Glassc5951992017-08-03 12:22:17 -060088 return -EIO;
Simon Glassd3716dd2019-08-01 09:47:08 -060089 env_new.flags = ENV_REDUND_ACTIVE;
Wolfgang Denkea882ba2010-06-20 23:33:59 +020090
Simon Glass203e94f2017-08-03 12:21:56 -060091 if (gd->env_valid == ENV_VALID) {
Stefano Babica3110f02010-10-27 11:06:20 +020092 env_new_offset = CONFIG_ENV_OFFSET_REDUND;
93 env_offset = CONFIG_ENV_OFFSET;
94 } else {
95 env_new_offset = CONFIG_ENV_OFFSET;
96 env_offset = CONFIG_ENV_OFFSET_REDUND;
97 }
98
Wolfgang Wegner7319bca2010-04-23 17:22:55 +020099 /* Is the sector larger than the env (i.e. embedded) */
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200100 if (sect_size > CONFIG_ENV_SIZE) {
101 saved_size = sect_size - CONFIG_ENV_SIZE;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200102 saved_offset = env_new_offset + CONFIG_ENV_SIZE;
Ravi Babu7dd01742015-08-17 13:29:49 +0530103 saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200104 if (!saved_buffer) {
Simon Glassc5951992017-08-03 12:22:17 -0600105 ret = -ENOMEM;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200106 goto done;
107 }
Heiko Schocher9ba5e5b2019-03-13 12:15:45 +0100108 ret = spi_flash_read(env_flash, saved_offset,
109 saved_size, saved_buffer);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200110 if (ret)
111 goto done;
112 }
113
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200114 sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200115
116 puts("Erasing SPI flash...");
117 ret = spi_flash_erase(env_flash, env_new_offset,
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200118 sector * sect_size);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200119 if (ret)
120 goto done;
121
122 puts("Writing to SPI flash...");
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200123
Stefano Babica3110f02010-10-27 11:06:20 +0200124 ret = spi_flash_write(env_flash, env_new_offset,
Tom Rinicd0f4fa2013-04-05 14:55:21 -0400125 CONFIG_ENV_SIZE, &env_new);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200126 if (ret)
127 goto done;
128
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200129 if (sect_size > CONFIG_ENV_SIZE) {
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200130 ret = spi_flash_write(env_flash, saved_offset,
131 saved_size, saved_buffer);
132 if (ret)
133 goto done;
134 }
135
Igor Grinbergeb58a7f2011-11-07 01:14:08 +0000136 ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
Tom Rinicd0f4fa2013-04-05 14:55:21 -0400137 sizeof(env_new.flags), &flag);
Stefano Babica3110f02010-10-27 11:06:20 +0200138 if (ret)
139 goto done;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200140
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200141 puts("done\n");
142
Simon Glass203e94f2017-08-03 12:21:56 -0600143 gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
Stefano Babica3110f02010-10-27 11:06:20 +0200144
thomas.langer@lantiq.com2dc55d92011-03-29 02:35:14 +0000145 printf("Valid environment: %d\n", (int)gd->env_valid);
Stefano Babica3110f02010-10-27 11:06:20 +0200146
Patrick Delaunayea5641e2021-01-04 14:41:31 +0100147done:
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200148 if (saved_buffer)
149 free(saved_buffer);
Igor Grinbergeb58a7f2011-11-07 01:14:08 +0000150
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200151 return ret;
152}
153
Simon Glassc5951992017-08-03 12:22:17 -0600154static int env_sf_load(void)
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200155{
156 int ret;
Simon Goldschmidt80719932018-01-31 14:47:13 +0100157 int read1_fail, read2_fail;
158 env_t *tmp_env1, *tmp_env2;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200159
Ravi Babu7dd01742015-08-17 13:29:49 +0530160 tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN,
161 CONFIG_ENV_SIZE);
162 tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN,
163 CONFIG_ENV_SIZE);
Wolfgang Denkea882ba2010-06-20 23:33:59 +0200164 if (!tmp_env1 || !tmp_env2) {
Simon Glass0ac7d722019-08-01 09:47:00 -0600165 env_set_default("malloc() failed", 0);
Simon Glassc5951992017-08-03 12:22:17 -0600166 ret = -EIO;
thomas.langer@lantiq.com2dc55d92011-03-29 02:35:14 +0000167 goto out;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200168 }
169
Andreas Fenkart8fee8842017-04-08 11:59:32 +0200170 ret = setup_flash_device();
171 if (ret)
thomas.langer@lantiq.com2dc55d92011-03-29 02:35:14 +0000172 goto out;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200173
Heiko Schocher9ba5e5b2019-03-13 12:15:45 +0100174 read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
175 CONFIG_ENV_SIZE, tmp_env1);
176 read2_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND,
177 CONFIG_ENV_SIZE, tmp_env2);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200178
Simon Goldschmidt80719932018-01-31 14:47:13 +0100179 ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
Marek Vasut890feec2020-07-07 20:51:35 +0200180 read2_fail, H_EXTERNAL);
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200181
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200182 spi_flash_free(env_flash);
183 env_flash = NULL;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200184out:
Wolfgang Denkea882ba2010-06-20 23:33:59 +0200185 free(tmp_env1);
186 free(tmp_env2);
Simon Glassc5951992017-08-03 12:22:17 -0600187
188 return ret;
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200189}
190#else
Simon Glasse5bce242017-08-03 12:22:01 -0600191static int env_sf_save(void)
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200192{
Rasmus Villemoesbcb44f62021-04-14 20:51:43 +0200193 u32 saved_size = 0, saved_offset = 0, sector;
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200194 u32 sect_size = CONFIG_ENV_SECT_SIZE;
Marek Vasut7ce15262014-03-05 19:59:50 +0100195 char *saved_buffer = NULL;
Igor Grinbergeb58a7f2011-11-07 01:14:08 +0000196 int ret = 1;
Tom Rinicd0f4fa2013-04-05 14:55:21 -0400197 env_t env_new;
Gong Qianyu19c31282016-01-26 15:06:42 +0800198
Andreas Fenkartafa81a72017-04-08 11:59:31 +0200199 ret = setup_flash_device();
200 if (ret)
201 return ret;
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200202
Rasmus Villemoesbcb44f62021-04-14 20:51:43 +0200203 if (IS_ENABLED(CONFIG_ENV_SECT_SIZE_AUTO))
204 sect_size = env_flash->mtd.erasesize;
205
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500206 /* Is the sector larger than the env (i.e. embedded) */
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200207 if (sect_size > CONFIG_ENV_SIZE) {
208 saved_size = sect_size - CONFIG_ENV_SIZE;
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500209 saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
210 saved_buffer = malloc(saved_size);
Igor Grinbergeb58a7f2011-11-07 01:14:08 +0000211 if (!saved_buffer)
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500212 goto done;
Igor Grinbergeb58a7f2011-11-07 01:14:08 +0000213
Heiko Schocher9ba5e5b2019-03-13 12:15:45 +0100214 ret = spi_flash_read(env_flash, saved_offset,
215 saved_size, saved_buffer);
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500216 if (ret)
217 goto done;
218 }
219
Marek Vasut7ce15262014-03-05 19:59:50 +0100220 ret = env_export(&env_new);
221 if (ret)
Stefano Babica3110f02010-10-27 11:06:20 +0200222 goto done;
Stefano Babica3110f02010-10-27 11:06:20 +0200223
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200224 sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size);
Andreas Fenkart0b2e5bb2017-04-08 11:59:34 +0200225
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200226 puts("Erasing SPI flash...");
Stefano Babica3110f02010-10-27 11:06:20 +0200227 ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200228 sector * sect_size);
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500229 if (ret)
230 goto done;
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200231
232 puts("Writing to SPI flash...");
Stefano Babica3110f02010-10-27 11:06:20 +0200233 ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
Tom Rinicd0f4fa2013-04-05 14:55:21 -0400234 CONFIG_ENV_SIZE, &env_new);
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500235 if (ret)
236 goto done;
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200237
Rasmus Villemoes4da73472021-04-14 20:51:42 +0200238 if (sect_size > CONFIG_ENV_SIZE) {
Stefano Babica3110f02010-10-27 11:06:20 +0200239 ret = spi_flash_write(env_flash, saved_offset,
240 saved_size, saved_buffer);
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500241 if (ret)
242 goto done;
243 }
244
245 ret = 0;
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200246 puts("done\n");
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500247
Patrick Delaunayea5641e2021-01-04 14:41:31 +0100248done:
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500249 if (saved_buffer)
250 free(saved_buffer);
Igor Grinbergeb58a7f2011-11-07 01:14:08 +0000251
Mike Frysinger5b3375a2008-12-11 06:23:37 -0500252 return ret;
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200253}
254
Simon Glassc5951992017-08-03 12:22:17 -0600255static int env_sf_load(void)
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200256{
257 int ret;
Ying Zhang5a89fa92014-01-24 15:50:07 +0800258 char *buf = NULL;
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200259
Ravi Babu7dd01742015-08-17 13:29:49 +0530260 buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
Andreas Fenkartc041c602017-04-08 11:59:33 +0200261 if (!buf) {
Simon Glass0ac7d722019-08-01 09:47:00 -0600262 env_set_default("malloc() failed", 0);
Simon Glassc5951992017-08-03 12:22:17 -0600263 return -EIO;
Wolfgang Denkea882ba2010-06-20 23:33:59 +0200264 }
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200265
Andreas Fenkartc041c602017-04-08 11:59:33 +0200266 ret = setup_flash_device();
267 if (ret)
268 goto out;
269
Heiko Schocher9ba5e5b2019-03-13 12:15:45 +0100270 ret = spi_flash_read(env_flash,
271 CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
Wolfgang Denkea882ba2010-06-20 23:33:59 +0200272 if (ret) {
Simon Glass0ac7d722019-08-01 09:47:00 -0600273 env_set_default("spi_flash_read() failed", 0);
Andreas Fenkartc041c602017-04-08 11:59:33 +0200274 goto err_read;
Wolfgang Denkea882ba2010-06-20 23:33:59 +0200275 }
276
Marek Vasut890feec2020-07-07 20:51:35 +0200277 ret = env_import(buf, 1, H_EXTERNAL);
Simon Goldschmidt42a18202018-01-31 14:47:10 +0100278 if (!ret)
Simon Glass203e94f2017-08-03 12:21:56 -0600279 gd->env_valid = ENV_VALID;
Andreas Fenkartc041c602017-04-08 11:59:33 +0200280
281err_read:
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200282 spi_flash_free(env_flash);
283 env_flash = NULL;
Andreas Fenkartc041c602017-04-08 11:59:33 +0200284out:
285 free(buf);
Simon Glassc5951992017-08-03 12:22:17 -0600286
287 return ret;
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200288}
Wolfgang Wegner7319bca2010-04-23 17:22:55 +0200289#endif
Haavard Skinnemoen8c664972008-05-16 11:10:35 +0200290
Tom Rinia09fea12019-11-18 20:02:10 -0500291#if CONFIG_ENV_ADDR != 0x0
Rajesh Bhagat119c01c22018-11-05 18:01:15 +0000292__weak void *env_sf_get_env_addr(void)
293{
294 return (void *)CONFIG_ENV_ADDR;
295}
296#endif
297
Tom Rinia09fea12019-11-18 20:02:10 -0500298#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)
Heiko Schocher92765f452020-10-10 10:28:05 +0200299/*
300 * check if Environment on CONFIG_ENV_ADDR is valid.
301 */
302static int env_sf_init_addr(void)
Ashish Kumarb500c922017-12-14 17:37:08 +0530303{
Rajesh Bhagat119c01c22018-11-05 18:01:15 +0000304 env_t *env_ptr = (env_t *)env_sf_get_env_addr();
Ashish Kumarb500c922017-12-14 17:37:08 +0530305
306 if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
307 gd->env_addr = (ulong)&(env_ptr->data);
308 gd->env_valid = 1;
309 } else {
310 gd->env_addr = (ulong)&default_environment[0];
311 gd->env_valid = 1;
312 }
313
314 return 0;
315}
316#endif
317
Heiko Schocher92765f452020-10-10 10:28:05 +0200318#if defined(CONFIG_ENV_SPI_EARLY)
319/*
320 * early load environment from SPI flash (before relocation)
321 * and check if it is valid.
322 */
323static int env_sf_init_early(void)
324{
325 int ret;
326 int read1_fail;
327 int read2_fail;
328 int crc1_ok;
329 env_t *tmp_env2 = NULL;
330 env_t *tmp_env1;
331
332 /*
333 * if malloc is not ready yet, we cannot use
334 * this part yet.
335 */
336 if (!gd->malloc_limit)
337 return -ENOENT;
338
339 tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN,
340 CONFIG_ENV_SIZE);
341 if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
342 tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN,
343 CONFIG_ENV_SIZE);
344
345 if (!tmp_env1 || !tmp_env2)
346 goto out;
347
348 ret = setup_flash_device();
349 if (ret)
350 goto out;
351
352 read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
353 CONFIG_ENV_SIZE, tmp_env1);
354
355 if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) {
356 read2_fail = spi_flash_read(env_flash,
357 CONFIG_ENV_OFFSET_REDUND,
358 CONFIG_ENV_SIZE, tmp_env2);
359 ret = env_check_redund((char *)tmp_env1, read1_fail,
360 (char *)tmp_env2, read2_fail);
361
362 if (ret == -EIO || ret == -ENOMSG)
363 goto err_read;
364
365 if (gd->env_valid == ENV_VALID)
366 gd->env_addr = (unsigned long)&tmp_env1->data;
367 else
368 gd->env_addr = (unsigned long)&tmp_env2->data;
369 } else {
370 if (read1_fail)
371 goto err_read;
372
373 crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) ==
374 tmp_env1->crc;
375 if (!crc1_ok)
376 goto err_read;
377
378 /* if valid -> this is our env */
379 gd->env_valid = ENV_VALID;
380 gd->env_addr = (unsigned long)&tmp_env1->data;
381 }
382
383 return 0;
384err_read:
385 spi_flash_free(env_flash);
386 env_flash = NULL;
387 free(tmp_env1);
388 if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
389 free(tmp_env2);
390out:
391 /* env is not valid. always return 0 */
392 gd->env_valid = ENV_INVALID;
393 return 0;
394}
395#endif
396
397static int env_sf_init(void)
398{
399#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)
400 return env_sf_init_addr();
401#elif defined(CONFIG_ENV_SPI_EARLY)
402 return env_sf_init_early();
403#endif
404 /*
Heiko Schocher46ce9e72020-11-03 15:22:36 +0100405 * return here -ENOENT, so env_init()
406 * can set the init bit and later if no
407 * other Environment storage is defined
408 * can set the default environment
Heiko Schocher92765f452020-10-10 10:28:05 +0200409 */
Heiko Schocher46ce9e72020-11-03 15:22:36 +0100410 return -ENOENT;
Heiko Schocher92765f452020-10-10 10:28:05 +0200411}
412
Simon Glass4415f1d2017-08-03 12:21:58 -0600413U_BOOT_ENV_LOCATION(sf) = {
414 .location = ENVL_SPI_FLASH,
Patrick Delaunay22140d12020-07-28 11:51:16 +0200415 ENV_NAME("SPIFlash")
Simon Glasse5bce242017-08-03 12:22:01 -0600416 .load = env_sf_load,
Rasmus Villemoes6d3524c2020-03-27 00:02:00 +0100417 .save = CONFIG_IS_ENABLED(SAVEENV) ? ENV_SAVE_PTR(env_sf_save) : NULL,
Ashish Kumarb500c922017-12-14 17:37:08 +0530418 .init = env_sf_init,
Simon Glass4415f1d2017-08-03 12:21:58 -0600419};