blob: 06cc62e005c67c3f5643557a4b9390acd9dec831 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +02002/*
Wolfgang Denk460a9ff2010-06-20 23:33:59 +02003 * (C) Copyright 2000-2010
Haavard Skinnemoeneb8951c2008-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 Skinnemoeneb8951c2008-05-16 11:10:35 +020010 */
11#include <common.h>
Simon Glass11c89f32017-05-17 17:18:03 -060012#include <dm.h>
Simon Glass97385862019-08-01 09:47:00 -060013#include <env.h>
Simon Glass9d1f6192019-08-02 09:44:25 -060014#include <env_internal.h>
Simon Glass8e201882020-05-10 11:39:54 -060015#include <flash.h>
Mike Frysinger9af10d52008-12-11 06:23:37 -050016#include <malloc.h>
Simon Glassdef92152014-10-13 23:41:55 -060017#include <spi.h>
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +020018#include <spi_flash.h>
Wolfgang Denk460a9ff2010-06-20 23:33:59 +020019#include <search.h>
20#include <errno.h>
Simon Glass8e201882020-05-10 11:39:54 -060021#include <uuid.h>
Simon Glass274e0b02020-05-10 11:39:56 -060022#include <asm/cache.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060023#include <asm/global_data.h>
Gong Qianyu6d85a602016-01-26 15:06:42 +080024#include <dm/device-internal.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070025#include <u-boot/crc.h>
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +020026
Simon Glassc10a88e2017-08-03 12:21:58 -060027#ifndef CONFIG_SPL_BUILD
Ashish Kumara7bf68a2017-12-14 17:37:08 +053028#define INITENV
Simon Glassc10a88e2017-08-03 12:21:58 -060029#endif
30
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +020031#ifdef CONFIG_ENV_OFFSET_REDUND
Igor Grinbergc3c1bed2011-11-07 01:14:08 +000032static ulong env_offset = CONFIG_ENV_OFFSET;
33static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND;
Stefano Babic5f6c2862010-10-27 11:06:20 +020034#endif /* CONFIG_ENV_OFFSET_REDUND */
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +020035
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +020036DECLARE_GLOBAL_DATA_PTR;
37
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +020038static struct spi_flash *env_flash;
39
Andreas Fenkart52b94442017-04-08 11:59:31 +020040static int setup_flash_device(void)
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +020041{
Lukasz Majewski76f442982020-06-04 23:11:53 +080042#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
Gong Qianyu6d85a602016-01-26 15:06:42 +080043 struct udevice *new;
Andreas Fenkart52b94442017-04-08 11:59:31 +020044 int ret;
Gong Qianyu6d85a602016-01-26 15:06:42 +080045
Vignesh Rae569792016-07-06 10:04:28 +053046 /* speed and mode will be read from DT */
Gong Qianyu6d85a602016-01-26 15:06:42 +080047 ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
Konstantin Porotchkin0be67b22018-08-29 16:34:52 +030048 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE,
49 &new);
Gong Qianyu6d85a602016-01-26 15:06:42 +080050 if (ret) {
Simon Glass97385862019-08-01 09:47:00 -060051 env_set_default("spi_flash_probe_bus_cs() failed", 0);
Simon Glass99778492017-08-03 12:22:17 -060052 return ret;
Gong Qianyu6d85a602016-01-26 15:06:42 +080053 }
54
55 env_flash = dev_get_uclass_priv(new);
56#else
Jagan Teki90173092020-05-13 16:32:42 +053057 if (env_flash)
58 spi_flash_free(env_flash);
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +020059
Jagan Teki90173092020-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 Wegner0cae3d42010-04-23 17:22:55 +020062 if (!env_flash) {
Jagan Teki90173092020-05-13 16:32:42 +053063 env_set_default("spi_flash_probe() failed", 0);
64 return -EIO;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +020065 }
Gong Qianyu6d85a602016-01-26 15:06:42 +080066#endif
Andreas Fenkart52b94442017-04-08 11:59:31 +020067 return 0;
68}
69
70#if defined(CONFIG_ENV_OFFSET_REDUND)
Simon Glass082af922017-08-03 12:22:01 -060071static int env_sf_save(void)
Andreas Fenkart52b94442017-04-08 11:59:31 +020072{
73 env_t env_new;
Simon Glass4686d8f2019-08-01 09:47:08 -060074 char *saved_buffer = NULL, flag = ENV_REDUND_OBSOLETE;
Rasmus Villemoese535f5b2021-04-14 20:51:43 +020075 u32 saved_size = 0, saved_offset = 0, sector;
Rasmus Villemoes1ee19842021-04-14 20:51:42 +020076 u32 sect_size = CONFIG_ENV_SECT_SIZE;
Andreas Fenkart52b94442017-04-08 11:59:31 +020077 int ret;
78
79 ret = setup_flash_device();
80 if (ret)
81 return ret;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +020082
Rasmus Villemoese535f5b2021-04-14 20:51:43 +020083 if (IS_ENABLED(CONFIG_ENV_SECT_SIZE_AUTO))
84 sect_size = env_flash->mtd.erasesize;
85
Marek Vasutd73c1292014-03-05 19:59:50 +010086 ret = env_export(&env_new);
87 if (ret)
Simon Glass99778492017-08-03 12:22:17 -060088 return -EIO;
Simon Glass4686d8f2019-08-01 09:47:08 -060089 env_new.flags = ENV_REDUND_ACTIVE;
Wolfgang Denk460a9ff2010-06-20 23:33:59 +020090
Simon Glass4bc2ad22017-08-03 12:21:56 -060091 if (gd->env_valid == ENV_VALID) {
Stefano Babic5f6c2862010-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 Wegner0cae3d42010-04-23 17:22:55 +020099 /* Is the sector larger than the env (i.e. embedded) */
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200100 if (sect_size > CONFIG_ENV_SIZE) {
101 saved_size = sect_size - CONFIG_ENV_SIZE;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200102 saved_offset = env_new_offset + CONFIG_ENV_SIZE;
Ravi Babu20d93fc2015-08-17 13:29:49 +0530103 saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size);
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200104 if (!saved_buffer) {
Simon Glass99778492017-08-03 12:22:17 -0600105 ret = -ENOMEM;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200106 goto done;
107 }
Heiko Schocherf45775c2019-03-13 12:15:45 +0100108 ret = spi_flash_read(env_flash, saved_offset,
109 saved_size, saved_buffer);
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200110 if (ret)
111 goto done;
112 }
113
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200114 sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size);
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200115
116 puts("Erasing SPI flash...");
117 ret = spi_flash_erase(env_flash, env_new_offset,
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200118 sector * sect_size);
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200119 if (ret)
120 goto done;
121
122 puts("Writing to SPI flash...");
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200123
Stefano Babic5f6c2862010-10-27 11:06:20 +0200124 ret = spi_flash_write(env_flash, env_new_offset,
Tom Rinia840b8e2013-04-05 14:55:21 -0400125 CONFIG_ENV_SIZE, &env_new);
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200126 if (ret)
127 goto done;
128
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200129 if (sect_size > CONFIG_ENV_SIZE) {
Wolfgang Wegner0cae3d42010-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 Grinbergc3c1bed2011-11-07 01:14:08 +0000136 ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
Tom Rinia840b8e2013-04-05 14:55:21 -0400137 sizeof(env_new.flags), &flag);
Stefano Babic5f6c2862010-10-27 11:06:20 +0200138 if (ret)
139 goto done;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200140
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200141 puts("done\n");
142
Simon Glass4bc2ad22017-08-03 12:21:56 -0600143 gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
Stefano Babic5f6c2862010-10-27 11:06:20 +0200144
thomas.langer@lantiq.com97dfdcf2011-03-29 02:35:14 +0000145 printf("Valid environment: %d\n", (int)gd->env_valid);
Stefano Babic5f6c2862010-10-27 11:06:20 +0200146
Patrick Delaunay480b6e62021-01-04 14:41:31 +0100147done:
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200148 if (saved_buffer)
149 free(saved_buffer);
Igor Grinbergc3c1bed2011-11-07 01:14:08 +0000150
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200151 return ret;
152}
153
Simon Glass99778492017-08-03 12:22:17 -0600154static int env_sf_load(void)
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200155{
156 int ret;
Simon Goldschmidt8f9ce3a2018-01-31 14:47:13 +0100157 int read1_fail, read2_fail;
158 env_t *tmp_env1, *tmp_env2;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200159
Ravi Babu20d93fc2015-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 Denk460a9ff2010-06-20 23:33:59 +0200164 if (!tmp_env1 || !tmp_env2) {
Simon Glass97385862019-08-01 09:47:00 -0600165 env_set_default("malloc() failed", 0);
Simon Glass99778492017-08-03 12:22:17 -0600166 ret = -EIO;
thomas.langer@lantiq.com97dfdcf2011-03-29 02:35:14 +0000167 goto out;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200168 }
169
Andreas Fenkarta2d18832017-04-08 11:59:32 +0200170 ret = setup_flash_device();
171 if (ret)
thomas.langer@lantiq.com97dfdcf2011-03-29 02:35:14 +0000172 goto out;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200173
Heiko Schocherf45775c2019-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 Wegner0cae3d42010-04-23 17:22:55 +0200178
Simon Goldschmidt8f9ce3a2018-01-31 14:47:13 +0100179 ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
Marek Vasutdfe4b7e2020-07-07 20:51:35 +0200180 read2_fail, H_EXTERNAL);
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200181
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200182 spi_flash_free(env_flash);
183 env_flash = NULL;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200184out:
Wolfgang Denk460a9ff2010-06-20 23:33:59 +0200185 free(tmp_env1);
186 free(tmp_env2);
Simon Glass99778492017-08-03 12:22:17 -0600187
188 return ret;
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200189}
190#else
Simon Glass082af922017-08-03 12:22:01 -0600191static int env_sf_save(void)
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200192{
Rasmus Villemoese535f5b2021-04-14 20:51:43 +0200193 u32 saved_size = 0, saved_offset = 0, sector;
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200194 u32 sect_size = CONFIG_ENV_SECT_SIZE;
Marek Vasutd73c1292014-03-05 19:59:50 +0100195 char *saved_buffer = NULL;
Igor Grinbergc3c1bed2011-11-07 01:14:08 +0000196 int ret = 1;
Tom Rinia840b8e2013-04-05 14:55:21 -0400197 env_t env_new;
Gong Qianyu6d85a602016-01-26 15:06:42 +0800198
Andreas Fenkart52b94442017-04-08 11:59:31 +0200199 ret = setup_flash_device();
200 if (ret)
201 return ret;
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200202
Rasmus Villemoese535f5b2021-04-14 20:51:43 +0200203 if (IS_ENABLED(CONFIG_ENV_SECT_SIZE_AUTO))
204 sect_size = env_flash->mtd.erasesize;
205
Mike Frysinger9af10d52008-12-11 06:23:37 -0500206 /* Is the sector larger than the env (i.e. embedded) */
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200207 if (sect_size > CONFIG_ENV_SIZE) {
208 saved_size = sect_size - CONFIG_ENV_SIZE;
Mike Frysinger9af10d52008-12-11 06:23:37 -0500209 saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
210 saved_buffer = malloc(saved_size);
Igor Grinbergc3c1bed2011-11-07 01:14:08 +0000211 if (!saved_buffer)
Mike Frysinger9af10d52008-12-11 06:23:37 -0500212 goto done;
Igor Grinbergc3c1bed2011-11-07 01:14:08 +0000213
Heiko Schocherf45775c2019-03-13 12:15:45 +0100214 ret = spi_flash_read(env_flash, saved_offset,
215 saved_size, saved_buffer);
Mike Frysinger9af10d52008-12-11 06:23:37 -0500216 if (ret)
217 goto done;
218 }
219
Marek Vasutd73c1292014-03-05 19:59:50 +0100220 ret = env_export(&env_new);
221 if (ret)
Stefano Babic5f6c2862010-10-27 11:06:20 +0200222 goto done;
Stefano Babic5f6c2862010-10-27 11:06:20 +0200223
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200224 sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size);
Andreas Fenkartdf701912017-04-08 11:59:34 +0200225
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200226 puts("Erasing SPI flash...");
Stefano Babic5f6c2862010-10-27 11:06:20 +0200227 ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200228 sector * sect_size);
Mike Frysinger9af10d52008-12-11 06:23:37 -0500229 if (ret)
230 goto done;
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200231
232 puts("Writing to SPI flash...");
Stefano Babic5f6c2862010-10-27 11:06:20 +0200233 ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
Tom Rinia840b8e2013-04-05 14:55:21 -0400234 CONFIG_ENV_SIZE, &env_new);
Mike Frysinger9af10d52008-12-11 06:23:37 -0500235 if (ret)
236 goto done;
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200237
Rasmus Villemoes1ee19842021-04-14 20:51:42 +0200238 if (sect_size > CONFIG_ENV_SIZE) {
Stefano Babic5f6c2862010-10-27 11:06:20 +0200239 ret = spi_flash_write(env_flash, saved_offset,
240 saved_size, saved_buffer);
Mike Frysinger9af10d52008-12-11 06:23:37 -0500241 if (ret)
242 goto done;
243 }
244
245 ret = 0;
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200246 puts("done\n");
Mike Frysinger9af10d52008-12-11 06:23:37 -0500247
Patrick Delaunay480b6e62021-01-04 14:41:31 +0100248done:
Mike Frysinger9af10d52008-12-11 06:23:37 -0500249 if (saved_buffer)
250 free(saved_buffer);
Igor Grinbergc3c1bed2011-11-07 01:14:08 +0000251
Mike Frysinger9af10d52008-12-11 06:23:37 -0500252 return ret;
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200253}
254
Simon Glass99778492017-08-03 12:22:17 -0600255static int env_sf_load(void)
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200256{
257 int ret;
Ying Zhang354846f2014-01-24 15:50:07 +0800258 char *buf = NULL;
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200259
Ravi Babu20d93fc2015-08-17 13:29:49 +0530260 buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
Andreas Fenkarta2c65852017-04-08 11:59:33 +0200261 if (!buf) {
Simon Glass97385862019-08-01 09:47:00 -0600262 env_set_default("malloc() failed", 0);
Simon Glass99778492017-08-03 12:22:17 -0600263 return -EIO;
Wolfgang Denk460a9ff2010-06-20 23:33:59 +0200264 }
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200265
Andreas Fenkarta2c65852017-04-08 11:59:33 +0200266 ret = setup_flash_device();
267 if (ret)
268 goto out;
269
Heiko Schocherf45775c2019-03-13 12:15:45 +0100270 ret = spi_flash_read(env_flash,
271 CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
Wolfgang Denk460a9ff2010-06-20 23:33:59 +0200272 if (ret) {
Simon Glass97385862019-08-01 09:47:00 -0600273 env_set_default("spi_flash_read() failed", 0);
Andreas Fenkarta2c65852017-04-08 11:59:33 +0200274 goto err_read;
Wolfgang Denk460a9ff2010-06-20 23:33:59 +0200275 }
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200276
Marek Vasutdfe4b7e2020-07-07 20:51:35 +0200277 ret = env_import(buf, 1, H_EXTERNAL);
Simon Goldschmidt32c3eb52018-01-31 14:47:10 +0100278 if (!ret)
Simon Glass4bc2ad22017-08-03 12:21:56 -0600279 gd->env_valid = ENV_VALID;
Andreas Fenkarta2c65852017-04-08 11:59:33 +0200280
281err_read:
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200282 spi_flash_free(env_flash);
283 env_flash = NULL;
Andreas Fenkarta2c65852017-04-08 11:59:33 +0200284out:
285 free(buf);
Simon Glass99778492017-08-03 12:22:17 -0600286
287 return ret;
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200288}
Wolfgang Wegner0cae3d42010-04-23 17:22:55 +0200289#endif
Haavard Skinnemoeneb8951c2008-05-16 11:10:35 +0200290
Tom Rini5cd7ece2019-11-18 20:02:10 -0500291#if CONFIG_ENV_ADDR != 0x0
Rajesh Bhagat9a90cc92018-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 Rini5cd7ece2019-11-18 20:02:10 -0500298#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)
Heiko Schocher704d21c2020-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 Kumara7bf68a2017-12-14 17:37:08 +0530303{
Rajesh Bhagat9a90cc92018-11-05 18:01:15 +0000304 env_t *env_ptr = (env_t *)env_sf_get_env_addr();
Ashish Kumara7bf68a2017-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 Schocher704d21c2020-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 Schocher8ba7b612020-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 Schocher704d21c2020-10-10 10:28:05 +0200409 */
Heiko Schocher8ba7b612020-11-03 15:22:36 +0100410 return -ENOENT;
Heiko Schocher704d21c2020-10-10 10:28:05 +0200411}
412
Simon Glassc10a88e2017-08-03 12:21:58 -0600413U_BOOT_ENV_LOCATION(sf) = {
414 .location = ENVL_SPI_FLASH,
Patrick Delaunaya4433de2020-07-28 11:51:16 +0200415 ENV_NAME("SPIFlash")
Simon Glass082af922017-08-03 12:22:01 -0600416 .load = env_sf_load,
Rasmus Villemoesfcff09a2020-03-27 00:02:00 +0100417 .save = CONFIG_IS_ENABLED(SAVEENV) ? ENV_SAVE_PTR(env_sf_save) : NULL,
Ashish Kumara7bf68a2017-12-14 17:37:08 +0530418 .init = env_sf_init,
Simon Glassc10a88e2017-08-03 12:21:58 -0600419};