Blame view

common/env_sf.c 7.21 KB
8c66497e0   Haavard Skinnemoen   Add support for e...
1
  /*
ea882baf9   Wolfgang Denk   New implementatio...
2
   * (C) Copyright 2000-2010
8c66497e0   Haavard Skinnemoen   Add support for e...
3
4
5
6
7
8
9
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   *
   * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   * Andreas Heppel <aheppel@sysgo.de>
   *
   * (C) Copyright 2008 Atmel Corporation
   *
402ba1e3a   Jagannadha Sutradharudu Teki   cmd_sf|env_sf: Fi...
10
   * SPDX-License-Identifier:	GPL-2.0+
8c66497e0   Haavard Skinnemoen   Add support for e...
11
12
   */
  #include <common.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
13
  #include <environment.h>
5b3375ac8   Mike Frysinger   env_sf: support e...
14
  #include <malloc.h>
843c9e879   Simon Glass   dm: Add spi.h hea...
15
  #include <spi.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
16
  #include <spi_flash.h>
ea882baf9   Wolfgang Denk   New implementatio...
17
18
  #include <search.h>
  #include <errno.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
19

0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
20
21
  #ifndef CONFIG_ENV_SPI_BUS
  # define CONFIG_ENV_SPI_BUS	0
8c66497e0   Haavard Skinnemoen   Add support for e...
22
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
23
  #ifndef CONFIG_ENV_SPI_CS
eb58a7fc7   Igor Grinberg   env: clean env_sf...
24
  # define CONFIG_ENV_SPI_CS	0
8c66497e0   Haavard Skinnemoen   Add support for e...
25
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
26
27
  #ifndef CONFIG_ENV_SPI_MAX_HZ
  # define CONFIG_ENV_SPI_MAX_HZ	1000000
8c66497e0   Haavard Skinnemoen   Add support for e...
28
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
29
30
  #ifndef CONFIG_ENV_SPI_MODE
  # define CONFIG_ENV_SPI_MODE	SPI_MODE_3
8c66497e0   Haavard Skinnemoen   Add support for e...
31
  #endif
7319bcaf8   Wolfgang Wegner   add redundant env...
32
  #ifdef CONFIG_ENV_OFFSET_REDUND
eb58a7fc7   Igor Grinberg   env: clean env_sf...
33
34
  static ulong env_offset		= CONFIG_ENV_OFFSET;
  static ulong env_new_offset	= CONFIG_ENV_OFFSET_REDUND;
7319bcaf8   Wolfgang Wegner   add redundant env...
35

eb58a7fc7   Igor Grinberg   env: clean env_sf...
36
37
  #define ACTIVE_FLAG	1
  #define OBSOLETE_FLAG	0
a3110f01c   Stefano Babic   env_sf: updated t...
38
  #endif /* CONFIG_ENV_OFFSET_REDUND */
7319bcaf8   Wolfgang Wegner   add redundant env...
39

8c66497e0   Haavard Skinnemoen   Add support for e...
40
  DECLARE_GLOBAL_DATA_PTR;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
41
  char *env_name_spec = "SPI Flash";
8c66497e0   Haavard Skinnemoen   Add support for e...
42
43
  
  static struct spi_flash *env_flash;
7319bcaf8   Wolfgang Wegner   add redundant env...
44
  #if defined(CONFIG_ENV_OFFSET_REDUND)
7319bcaf8   Wolfgang Wegner   add redundant env...
45
46
  int saveenv(void)
  {
cd0f4fa1c   Tom Rini   Revert "env: fix ...
47
  	env_t	env_new;
7ce1526ed   Marek Vasut   env: Add env_expo...
48
  	char	*saved_buffer = NULL, flag = OBSOLETE_FLAG;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
49
  	u32	saved_size, saved_offset, sector = 1;
ea882baf9   Wolfgang Denk   New implementatio...
50
  	int	ret;
7319bcaf8   Wolfgang Wegner   add redundant env...
51
52
  
  	if (!env_flash) {
a3110f01c   Stefano Babic   env_sf: updated t...
53
54
55
56
57
58
59
  		env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
  			CONFIG_ENV_SPI_CS,
  			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  		if (!env_flash) {
  			set_default_env("!spi_flash_probe() failed");
  			return 1;
  		}
7319bcaf8   Wolfgang Wegner   add redundant env...
60
  	}
7ce1526ed   Marek Vasut   env: Add env_expo...
61
62
63
  	ret = env_export(&env_new);
  	if (ret)
  		return ret;
cd0f4fa1c   Tom Rini   Revert "env: fix ...
64
  	env_new.flags	= ACTIVE_FLAG;
ea882baf9   Wolfgang Denk   New implementatio...
65

a3110f01c   Stefano Babic   env_sf: updated t...
66
67
68
69
70
71
72
  	if (gd->env_valid == 1) {
  		env_new_offset = CONFIG_ENV_OFFSET_REDUND;
  		env_offset = CONFIG_ENV_OFFSET;
  	} else {
  		env_new_offset = CONFIG_ENV_OFFSET;
  		env_offset = CONFIG_ENV_OFFSET_REDUND;
  	}
7319bcaf8   Wolfgang Wegner   add redundant env...
73
74
75
76
  	/* Is the sector larger than the env (i.e. embedded) */
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  		saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
  		saved_offset = env_new_offset + CONFIG_ENV_SIZE;
7dd017446   Ravi Babu   env: use cache li...
77
  		saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size);
7319bcaf8   Wolfgang Wegner   add redundant env...
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  		if (!saved_buffer) {
  			ret = 1;
  			goto done;
  		}
  		ret = spi_flash_read(env_flash, saved_offset,
  					saved_size, saved_buffer);
  		if (ret)
  			goto done;
  	}
  
  	if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
  		sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
  		if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
  			sector++;
  	}
  
  	puts("Erasing SPI flash...");
  	ret = spi_flash_erase(env_flash, env_new_offset,
  				sector * CONFIG_ENV_SECT_SIZE);
  	if (ret)
  		goto done;
  
  	puts("Writing to SPI flash...");
7319bcaf8   Wolfgang Wegner   add redundant env...
101

a3110f01c   Stefano Babic   env_sf: updated t...
102
  	ret = spi_flash_write(env_flash, env_new_offset,
cd0f4fa1c   Tom Rini   Revert "env: fix ...
103
  		CONFIG_ENV_SIZE, &env_new);
7319bcaf8   Wolfgang Wegner   add redundant env...
104
105
106
107
108
109
110
111
112
  	if (ret)
  		goto done;
  
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  		ret = spi_flash_write(env_flash, saved_offset,
  					saved_size, saved_buffer);
  		if (ret)
  			goto done;
  	}
eb58a7fc7   Igor Grinberg   env: clean env_sf...
113
  	ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
cd0f4fa1c   Tom Rini   Revert "env: fix ...
114
  				sizeof(env_new.flags), &flag);
a3110f01c   Stefano Babic   env_sf: updated t...
115
116
  	if (ret)
  		goto done;
7319bcaf8   Wolfgang Wegner   add redundant env...
117

7319bcaf8   Wolfgang Wegner   add redundant env...
118
119
  	puts("done
  ");
eb58a7fc7   Igor Grinberg   env: clean env_sf...
120
  	gd->env_valid = gd->env_valid == 2 ? 1 : 2;
a3110f01c   Stefano Babic   env_sf: updated t...
121

2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
122
123
  	printf("Valid environment: %d
  ", (int)gd->env_valid);
a3110f01c   Stefano Babic   env_sf: updated t...
124

7319bcaf8   Wolfgang Wegner   add redundant env...
125
126
127
   done:
  	if (saved_buffer)
  		free(saved_buffer);
eb58a7fc7   Igor Grinberg   env: clean env_sf...
128

7319bcaf8   Wolfgang Wegner   add redundant env...
129
130
131
132
133
134
135
136
137
  	return ret;
  }
  
  void env_relocate_spec(void)
  {
  	int ret;
  	int crc1_ok = 0, crc2_ok = 0;
  	env_t *tmp_env1 = NULL;
  	env_t *tmp_env2 = NULL;
a3110f01c   Stefano Babic   env_sf: updated t...
138
  	env_t *ep = NULL;
7319bcaf8   Wolfgang Wegner   add redundant env...
139

7dd017446   Ravi Babu   env: use cache li...
140
141
142
143
  	tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN,
  			CONFIG_ENV_SIZE);
  	tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN,
  			CONFIG_ENV_SIZE);
ea882baf9   Wolfgang Denk   New implementatio...
144
  	if (!tmp_env1 || !tmp_env2) {
ea882baf9   Wolfgang Denk   New implementatio...
145
  		set_default_env("!malloc() failed");
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
146
  		goto out;
7319bcaf8   Wolfgang Wegner   add redundant env...
147
148
149
150
  	}
  
  	env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
  			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
ea882baf9   Wolfgang Denk   New implementatio...
151
152
  	if (!env_flash) {
  		set_default_env("!spi_flash_probe() failed");
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
153
  		goto out;
ea882baf9   Wolfgang Denk   New implementatio...
154
  	}
7319bcaf8   Wolfgang Wegner   add redundant env...
155
156
157
  
  	ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
  				CONFIG_ENV_SIZE, tmp_env1);
ea882baf9   Wolfgang Denk   New implementatio...
158
159
  	if (ret) {
  		set_default_env("!spi_flash_read() failed");
7319bcaf8   Wolfgang Wegner   add redundant env...
160
  		goto err_read;
ea882baf9   Wolfgang Denk   New implementatio...
161
  	}
7319bcaf8   Wolfgang Wegner   add redundant env...
162
163
164
  
  	if (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc)
  		crc1_ok = 1;
7319bcaf8   Wolfgang Wegner   add redundant env...
165
166
167
168
169
170
  
  	ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND,
  				CONFIG_ENV_SIZE, tmp_env2);
  	if (!ret) {
  		if (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc)
  			crc2_ok = 1;
7319bcaf8   Wolfgang Wegner   add redundant env...
171
  	}
a3110f01c   Stefano Babic   env_sf: updated t...
172
  	if (!crc1_ok && !crc2_ok) {
a3110f01c   Stefano Babic   env_sf: updated t...
173
  		set_default_env("!bad CRC");
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
174
  		goto err_read;
a3110f01c   Stefano Babic   env_sf: updated t...
175
  	} else if (crc1_ok && !crc2_ok) {
7319bcaf8   Wolfgang Wegner   add redundant env...
176
  		gd->env_valid = 1;
7319bcaf8   Wolfgang Wegner   add redundant env...
177
  	} else if (!crc1_ok && crc2_ok) {
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
178
179
180
  		gd->env_valid = 2;
  	} else if (tmp_env1->flags == ACTIVE_FLAG &&
  		   tmp_env2->flags == OBSOLETE_FLAG) {
7319bcaf8   Wolfgang Wegner   add redundant env...
181
  		gd->env_valid = 1;
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
182
183
  	} else if (tmp_env1->flags == OBSOLETE_FLAG &&
  		   tmp_env2->flags == ACTIVE_FLAG) {
a3110f01c   Stefano Babic   env_sf: updated t...
184
  		gd->env_valid = 2;
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
185
  	} else if (tmp_env1->flags == tmp_env2->flags) {
5e8397dd9   Mario Schuknecht   env_sf: Fix recov...
186
  		gd->env_valid = 1;
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
187
  	} else if (tmp_env1->flags == 0xFF) {
5e8397dd9   Mario Schuknecht   env_sf: Fix recov...
188
189
  		gd->env_valid = 1;
  	} else if (tmp_env2->flags == 0xFF) {
7319bcaf8   Wolfgang Wegner   add redundant env...
190
  		gd->env_valid = 2;
7319bcaf8   Wolfgang Wegner   add redundant env...
191
192
193
194
195
  	} else {
  		/*
  		 * this differs from code in env_flash.c, but I think a sane
  		 * default path is desirable.
  		 */
5e8397dd9   Mario Schuknecht   env_sf: Fix recov...
196
  		gd->env_valid = 1;
7319bcaf8   Wolfgang Wegner   add redundant env...
197
  	}
ea882baf9   Wolfgang Denk   New implementatio...
198

a3110f01c   Stefano Babic   env_sf: updated t...
199
200
201
202
203
204
205
206
207
208
  	if (gd->env_valid == 1)
  		ep = tmp_env1;
  	else
  		ep = tmp_env2;
  
  	ret = env_import((char *)ep, 0);
  	if (!ret) {
  		error("Cannot import environment: errno = %d
  ", errno);
  		set_default_env("env_import failed");
7319bcaf8   Wolfgang Wegner   add redundant env...
209
  	}
7319bcaf8   Wolfgang Wegner   add redundant env...
210
211
212
213
  
  err_read:
  	spi_flash_free(env_flash);
  	env_flash = NULL;
7319bcaf8   Wolfgang Wegner   add redundant env...
214
  out:
ea882baf9   Wolfgang Denk   New implementatio...
215
216
  	free(tmp_env1);
  	free(tmp_env2);
7319bcaf8   Wolfgang Wegner   add redundant env...
217
218
  }
  #else
8c66497e0   Haavard Skinnemoen   Add support for e...
219
220
  int saveenv(void)
  {
eb58a7fc7   Igor Grinberg   env: clean env_sf...
221
  	u32	saved_size, saved_offset, sector = 1;
7ce1526ed   Marek Vasut   env: Add env_expo...
222
  	char	*saved_buffer = NULL;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
223
  	int	ret = 1;
cd0f4fa1c   Tom Rini   Revert "env: fix ...
224
  	env_t	env_new;
07efc9e32   TsiChung Liew   Change CFG_ENV_SI...
225

8c66497e0   Haavard Skinnemoen   Add support for e...
226
  	if (!env_flash) {
a3110f01c   Stefano Babic   env_sf: updated t...
227
228
229
230
231
232
233
  		env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
  			CONFIG_ENV_SPI_CS,
  			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  		if (!env_flash) {
  			set_default_env("!spi_flash_probe() failed");
  			return 1;
  		}
8c66497e0   Haavard Skinnemoen   Add support for e...
234
  	}
5b3375ac8   Mike Frysinger   env_sf: support e...
235
236
237
238
239
  	/* Is the sector larger than the env (i.e. embedded) */
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  		saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
  		saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
  		saved_buffer = malloc(saved_size);
eb58a7fc7   Igor Grinberg   env: clean env_sf...
240
  		if (!saved_buffer)
5b3375ac8   Mike Frysinger   env_sf: support e...
241
  			goto done;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
242

a3110f01c   Stefano Babic   env_sf: updated t...
243
244
  		ret = spi_flash_read(env_flash, saved_offset,
  			saved_size, saved_buffer);
5b3375ac8   Mike Frysinger   env_sf: support e...
245
246
247
  		if (ret)
  			goto done;
  	}
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
248
249
250
  	if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
  		sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
  		if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
07efc9e32   TsiChung Liew   Change CFG_ENV_SI...
251
252
  			sector++;
  	}
7ce1526ed   Marek Vasut   env: Add env_expo...
253
254
  	ret = env_export(&env_new);
  	if (ret)
a3110f01c   Stefano Babic   env_sf: updated t...
255
  		goto done;
a3110f01c   Stefano Babic   env_sf: updated t...
256

8c66497e0   Haavard Skinnemoen   Add support for e...
257
  	puts("Erasing SPI flash...");
a3110f01c   Stefano Babic   env_sf: updated t...
258
259
  	ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
  		sector * CONFIG_ENV_SECT_SIZE);
5b3375ac8   Mike Frysinger   env_sf: support e...
260
261
  	if (ret)
  		goto done;
8c66497e0   Haavard Skinnemoen   Add support for e...
262
263
  
  	puts("Writing to SPI flash...");
a3110f01c   Stefano Babic   env_sf: updated t...
264
  	ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
cd0f4fa1c   Tom Rini   Revert "env: fix ...
265
  		CONFIG_ENV_SIZE, &env_new);
5b3375ac8   Mike Frysinger   env_sf: support e...
266
267
  	if (ret)
  		goto done;
8c66497e0   Haavard Skinnemoen   Add support for e...
268

5b3375ac8   Mike Frysinger   env_sf: support e...
269
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
a3110f01c   Stefano Babic   env_sf: updated t...
270
271
  		ret = spi_flash_write(env_flash, saved_offset,
  			saved_size, saved_buffer);
5b3375ac8   Mike Frysinger   env_sf: support e...
272
273
274
275
276
  		if (ret)
  			goto done;
  	}
  
  	ret = 0;
8c66497e0   Haavard Skinnemoen   Add support for e...
277
278
  	puts("done
  ");
5b3375ac8   Mike Frysinger   env_sf: support e...
279
280
281
282
  
   done:
  	if (saved_buffer)
  		free(saved_buffer);
eb58a7fc7   Igor Grinberg   env: clean env_sf...
283

5b3375ac8   Mike Frysinger   env_sf: support e...
284
  	return ret;
8c66497e0   Haavard Skinnemoen   Add support for e...
285
286
287
288
289
  }
  
  void env_relocate_spec(void)
  {
  	int ret;
5a89fa927   Ying Zhang   SPL: P2020RDB: fi...
290
  	char *buf = NULL;
8c66497e0   Haavard Skinnemoen   Add support for e...
291

7dd017446   Ravi Babu   env: use cache li...
292
  	buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
293
294
  	env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
  			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
ea882baf9   Wolfgang Denk   New implementatio...
295
296
  	if (!env_flash) {
  		set_default_env("!spi_flash_probe() failed");
5a89fa927   Ying Zhang   SPL: P2020RDB: fi...
297
298
  		if (buf)
  			free(buf);
ea882baf9   Wolfgang Denk   New implementatio...
299
300
  		return;
  	}
8c66497e0   Haavard Skinnemoen   Add support for e...
301

ea882baf9   Wolfgang Denk   New implementatio...
302
303
304
305
306
307
  	ret = spi_flash_read(env_flash,
  		CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
  	if (ret) {
  		set_default_env("!spi_flash_read() failed");
  		goto out;
  	}
8c66497e0   Haavard Skinnemoen   Add support for e...
308

ea882baf9   Wolfgang Denk   New implementatio...
309
  	ret = env_import(buf, 1);
ea882baf9   Wolfgang Denk   New implementatio...
310
311
312
  	if (ret)
  		gd->env_valid = 1;
  out:
8c66497e0   Haavard Skinnemoen   Add support for e...
313
  	spi_flash_free(env_flash);
5a89fa927   Ying Zhang   SPL: P2020RDB: fi...
314
315
  	if (buf)
  		free(buf);
8c66497e0   Haavard Skinnemoen   Add support for e...
316
  	env_flash = NULL;
8c66497e0   Haavard Skinnemoen   Add support for e...
317
  }
7319bcaf8   Wolfgang Wegner   add redundant env...
318
  #endif
8c66497e0   Haavard Skinnemoen   Add support for e...
319
320
321
322
323
324
325
326
327
  
  int env_init(void)
  {
  	/* SPI flash isn't usable before relocation */
  	gd->env_addr = (ulong)&default_environment[0];
  	gd->env_valid = 1;
  
  	return 0;
  }