Blame view

env/sf.c 6.73 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>
9d922450a   Simon Glass   dm: Use dm.h head...
13
  #include <dm.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
14
  #include <environment.h>
5b3375ac8   Mike Frysinger   env_sf: support e...
15
  #include <malloc.h>
843c9e879   Simon Glass   dm: Add spi.h hea...
16
  #include <spi.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
17
  #include <spi_flash.h>
ea882baf9   Wolfgang Denk   New implementatio...
18
19
  #include <search.h>
  #include <errno.h>
19c31285a   Gong Qianyu   dm: env_sf: fix s...
20
  #include <dm/device-internal.h>
8c66497e0   Haavard Skinnemoen   Add support for e...
21

0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
22
  #ifndef CONFIG_ENV_SPI_BUS
2e4e5ad4c   Jean-Jacques Hiblot   common: env_sf: U...
23
  # define CONFIG_ENV_SPI_BUS	CONFIG_SF_DEFAULT_BUS
8c66497e0   Haavard Skinnemoen   Add support for e...
24
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
25
  #ifndef CONFIG_ENV_SPI_CS
2e4e5ad4c   Jean-Jacques Hiblot   common: env_sf: U...
26
  # define CONFIG_ENV_SPI_CS	CONFIG_SF_DEFAULT_CS
8c66497e0   Haavard Skinnemoen   Add support for e...
27
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
28
  #ifndef CONFIG_ENV_SPI_MAX_HZ
2e4e5ad4c   Jean-Jacques Hiblot   common: env_sf: U...
29
  # define CONFIG_ENV_SPI_MAX_HZ	CONFIG_SF_DEFAULT_SPEED
8c66497e0   Haavard Skinnemoen   Add support for e...
30
  #endif
0e8d15866   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ENV ma...
31
  #ifndef CONFIG_ENV_SPI_MODE
2e4e5ad4c   Jean-Jacques Hiblot   common: env_sf: U...
32
  # define CONFIG_ENV_SPI_MODE	CONFIG_SF_DEFAULT_MODE
8c66497e0   Haavard Skinnemoen   Add support for e...
33
  #endif
4415f1d1f   Simon Glass   env: Create a loc...
34
35
  #ifndef CONFIG_SPL_BUILD
  #define CMD_SAVEENV
b500c92b7   Ashish Kumar   env: sf: Add supp...
36
  #define INITENV
4415f1d1f   Simon Glass   env: Create a loc...
37
  #endif
7319bcaf8   Wolfgang Wegner   add redundant env...
38
  #ifdef CONFIG_ENV_OFFSET_REDUND
4415f1d1f   Simon Glass   env: Create a loc...
39
  #ifdef CMD_SAVEENV
eb58a7fc7   Igor Grinberg   env: clean env_sf...
40
41
  static ulong env_offset		= CONFIG_ENV_OFFSET;
  static ulong env_new_offset	= CONFIG_ENV_OFFSET_REDUND;
4415f1d1f   Simon Glass   env: Create a loc...
42
  #endif
7319bcaf8   Wolfgang Wegner   add redundant env...
43

eb58a7fc7   Igor Grinberg   env: clean env_sf...
44
45
  #define ACTIVE_FLAG	1
  #define OBSOLETE_FLAG	0
a3110f01c   Stefano Babic   env_sf: updated t...
46
  #endif /* CONFIG_ENV_OFFSET_REDUND */
7319bcaf8   Wolfgang Wegner   add redundant env...
47

8c66497e0   Haavard Skinnemoen   Add support for e...
48
  DECLARE_GLOBAL_DATA_PTR;
8c66497e0   Haavard Skinnemoen   Add support for e...
49
  static struct spi_flash *env_flash;
afa81a775   Andreas Fenkart   env_sf: factor ou...
50
  static int setup_flash_device(void)
7319bcaf8   Wolfgang Wegner   add redundant env...
51
  {
19c31285a   Gong Qianyu   dm: env_sf: fix s...
52
53
  #ifdef CONFIG_DM_SPI_FLASH
  	struct udevice *new;
afa81a775   Andreas Fenkart   env_sf: factor ou...
54
  	int	ret;
19c31285a   Gong Qianyu   dm: env_sf: fix s...
55

96907c0fe   Vignesh R   dm: spi: Read def...
56
  	/* speed and mode will be read from DT */
19c31285a   Gong Qianyu   dm: env_sf: fix s...
57
  	ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
96907c0fe   Vignesh R   dm: spi: Read def...
58
  				     0, 0, &new);
19c31285a   Gong Qianyu   dm: env_sf: fix s...
59
60
  	if (ret) {
  		set_default_env("!spi_flash_probe_bus_cs() failed");
c59519919   Simon Glass   env: Adjust the l...
61
  		return ret;
19c31285a   Gong Qianyu   dm: env_sf: fix s...
62
63
64
65
  	}
  
  	env_flash = dev_get_uclass_priv(new);
  #else
7319bcaf8   Wolfgang Wegner   add redundant env...
66
67
  
  	if (!env_flash) {
a3110f01c   Stefano Babic   env_sf: updated t...
68
69
70
71
72
  		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");
c59519919   Simon Glass   env: Adjust the l...
73
  			return -EIO;
a3110f01c   Stefano Babic   env_sf: updated t...
74
  		}
7319bcaf8   Wolfgang Wegner   add redundant env...
75
  	}
19c31285a   Gong Qianyu   dm: env_sf: fix s...
76
  #endif
afa81a775   Andreas Fenkart   env_sf: factor ou...
77
78
79
80
  	return 0;
  }
  
  #if defined(CONFIG_ENV_OFFSET_REDUND)
4415f1d1f   Simon Glass   env: Create a loc...
81
  #ifdef CMD_SAVEENV
e5bce247b   Simon Glass   env: Switch over ...
82
  static int env_sf_save(void)
afa81a775   Andreas Fenkart   env_sf: factor ou...
83
84
85
  {
  	env_t	env_new;
  	char	*saved_buffer = NULL, flag = OBSOLETE_FLAG;
0b2e5bbe6   Andreas Fenkart   env_sf: use DIV_R...
86
  	u32	saved_size, saved_offset, sector;
afa81a775   Andreas Fenkart   env_sf: factor ou...
87
88
89
90
91
  	int	ret;
  
  	ret = setup_flash_device();
  	if (ret)
  		return ret;
7319bcaf8   Wolfgang Wegner   add redundant env...
92

7ce1526ed   Marek Vasut   env: Add env_expo...
93
94
  	ret = env_export(&env_new);
  	if (ret)
c59519919   Simon Glass   env: Adjust the l...
95
  		return -EIO;
cd0f4fa1c   Tom Rini   Revert "env: fix ...
96
  	env_new.flags	= ACTIVE_FLAG;
ea882baf9   Wolfgang Denk   New implementatio...
97

203e94f6c   Simon Glass   env: Add an enum ...
98
  	if (gd->env_valid == ENV_VALID) {
a3110f01c   Stefano Babic   env_sf: updated t...
99
100
101
102
103
104
  		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...
105
106
107
108
  	/* 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...
109
  		saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size);
7319bcaf8   Wolfgang Wegner   add redundant env...
110
  		if (!saved_buffer) {
c59519919   Simon Glass   env: Adjust the l...
111
  			ret = -ENOMEM;
7319bcaf8   Wolfgang Wegner   add redundant env...
112
113
114
115
116
117
118
  			goto done;
  		}
  		ret = spi_flash_read(env_flash, saved_offset,
  					saved_size, saved_buffer);
  		if (ret)
  			goto done;
  	}
0b2e5bbe6   Andreas Fenkart   env_sf: use DIV_R...
119
  	sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE);
7319bcaf8   Wolfgang Wegner   add redundant env...
120
121
122
123
124
125
126
127
  
  	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...
128

a3110f01c   Stefano Babic   env_sf: updated t...
129
  	ret = spi_flash_write(env_flash, env_new_offset,
cd0f4fa1c   Tom Rini   Revert "env: fix ...
130
  		CONFIG_ENV_SIZE, &env_new);
7319bcaf8   Wolfgang Wegner   add redundant env...
131
132
133
134
135
136
137
138
139
  	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...
140
  	ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
cd0f4fa1c   Tom Rini   Revert "env: fix ...
141
  				sizeof(env_new.flags), &flag);
a3110f01c   Stefano Babic   env_sf: updated t...
142
143
  	if (ret)
  		goto done;
7319bcaf8   Wolfgang Wegner   add redundant env...
144

7319bcaf8   Wolfgang Wegner   add redundant env...
145
146
  	puts("done
  ");
203e94f6c   Simon Glass   env: Add an enum ...
147
  	gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
a3110f01c   Stefano Babic   env_sf: updated t...
148

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

7319bcaf8   Wolfgang Wegner   add redundant env...
152
153
154
   done:
  	if (saved_buffer)
  		free(saved_buffer);
eb58a7fc7   Igor Grinberg   env: clean env_sf...
155

7319bcaf8   Wolfgang Wegner   add redundant env...
156
157
  	return ret;
  }
4415f1d1f   Simon Glass   env: Create a loc...
158
  #endif /* CMD_SAVEENV */
7319bcaf8   Wolfgang Wegner   add redundant env...
159

c59519919   Simon Glass   env: Adjust the l...
160
  static int env_sf_load(void)
7319bcaf8   Wolfgang Wegner   add redundant env...
161
162
  {
  	int ret;
80719938c   Simon Goldschmidt   env: sf: use env_...
163
164
  	int read1_fail, read2_fail;
  	env_t *tmp_env1, *tmp_env2;
7319bcaf8   Wolfgang Wegner   add redundant env...
165

7dd017446   Ravi Babu   env: use cache li...
166
167
168
169
  	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...
170
  	if (!tmp_env1 || !tmp_env2) {
ea882baf9   Wolfgang Denk   New implementatio...
171
  		set_default_env("!malloc() failed");
c59519919   Simon Glass   env: Adjust the l...
172
  		ret = -EIO;
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
173
  		goto out;
7319bcaf8   Wolfgang Wegner   add redundant env...
174
  	}
8fee8845e   Andreas Fenkart   enf_sf: reuse set...
175
176
  	ret = setup_flash_device();
  	if (ret)
2dc55d9ed   thomas.langer@lantiq.com   fix redundant env...
177
  		goto out;
7319bcaf8   Wolfgang Wegner   add redundant env...
178

80719938c   Simon Goldschmidt   env: sf: use env_...
179
180
181
182
  	read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
  				    CONFIG_ENV_SIZE, tmp_env1);
  	read2_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND,
  				    CONFIG_ENV_SIZE, tmp_env2);
ea882baf9   Wolfgang Denk   New implementatio...
183

80719938c   Simon Goldschmidt   env: sf: use env_...
184
185
  	ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
  				read2_fail);
7319bcaf8   Wolfgang Wegner   add redundant env...
186

7319bcaf8   Wolfgang Wegner   add redundant env...
187
188
  	spi_flash_free(env_flash);
  	env_flash = NULL;
7319bcaf8   Wolfgang Wegner   add redundant env...
189
  out:
ea882baf9   Wolfgang Denk   New implementatio...
190
191
  	free(tmp_env1);
  	free(tmp_env2);
c59519919   Simon Glass   env: Adjust the l...
192
193
  
  	return ret;
7319bcaf8   Wolfgang Wegner   add redundant env...
194
195
  }
  #else
4415f1d1f   Simon Glass   env: Create a loc...
196
  #ifdef CMD_SAVEENV
e5bce247b   Simon Glass   env: Switch over ...
197
  static int env_sf_save(void)
8c66497e0   Haavard Skinnemoen   Add support for e...
198
  {
0b2e5bbe6   Andreas Fenkart   env_sf: use DIV_R...
199
  	u32	saved_size, saved_offset, sector;
7ce1526ed   Marek Vasut   env: Add env_expo...
200
  	char	*saved_buffer = NULL;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
201
  	int	ret = 1;
cd0f4fa1c   Tom Rini   Revert "env: fix ...
202
  	env_t	env_new;
19c31285a   Gong Qianyu   dm: env_sf: fix s...
203

afa81a775   Andreas Fenkart   env_sf: factor ou...
204
205
206
  	ret = setup_flash_device();
  	if (ret)
  		return ret;
8c66497e0   Haavard Skinnemoen   Add support for e...
207

5b3375ac8   Mike Frysinger   env_sf: support e...
208
209
210
211
212
  	/* 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...
213
  		if (!saved_buffer)
5b3375ac8   Mike Frysinger   env_sf: support e...
214
  			goto done;
eb58a7fc7   Igor Grinberg   env: clean env_sf...
215

a3110f01c   Stefano Babic   env_sf: updated t...
216
217
  		ret = spi_flash_read(env_flash, saved_offset,
  			saved_size, saved_buffer);
5b3375ac8   Mike Frysinger   env_sf: support e...
218
219
220
  		if (ret)
  			goto done;
  	}
7ce1526ed   Marek Vasut   env: Add env_expo...
221
222
  	ret = env_export(&env_new);
  	if (ret)
a3110f01c   Stefano Babic   env_sf: updated t...
223
  		goto done;
a3110f01c   Stefano Babic   env_sf: updated t...
224

0b2e5bbe6   Andreas Fenkart   env_sf: use DIV_R...
225
  	sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE);
8c66497e0   Haavard Skinnemoen   Add support for e...
226
  	puts("Erasing SPI flash...");
a3110f01c   Stefano Babic   env_sf: updated t...
227
228
  	ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
  		sector * CONFIG_ENV_SECT_SIZE);
5b3375ac8   Mike Frysinger   env_sf: support e...
229
230
  	if (ret)
  		goto done;
8c66497e0   Haavard Skinnemoen   Add support for e...
231
232
  
  	puts("Writing to SPI flash...");
a3110f01c   Stefano Babic   env_sf: updated t...
233
  	ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
cd0f4fa1c   Tom Rini   Revert "env: fix ...
234
  		CONFIG_ENV_SIZE, &env_new);
5b3375ac8   Mike Frysinger   env_sf: support e...
235
236
  	if (ret)
  		goto done;
8c66497e0   Haavard Skinnemoen   Add support for e...
237

5b3375ac8   Mike Frysinger   env_sf: support e...
238
  	if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
a3110f01c   Stefano Babic   env_sf: updated t...
239
240
  		ret = spi_flash_write(env_flash, saved_offset,
  			saved_size, saved_buffer);
5b3375ac8   Mike Frysinger   env_sf: support e...
241
242
243
244
245
  		if (ret)
  			goto done;
  	}
  
  	ret = 0;
8c66497e0   Haavard Skinnemoen   Add support for e...
246
247
  	puts("done
  ");
5b3375ac8   Mike Frysinger   env_sf: support e...
248
249
250
251
  
   done:
  	if (saved_buffer)
  		free(saved_buffer);
eb58a7fc7   Igor Grinberg   env: clean env_sf...
252

5b3375ac8   Mike Frysinger   env_sf: support e...
253
  	return ret;
8c66497e0   Haavard Skinnemoen   Add support for e...
254
  }
4415f1d1f   Simon Glass   env: Create a loc...
255
  #endif /* CMD_SAVEENV */
8c66497e0   Haavard Skinnemoen   Add support for e...
256

c59519919   Simon Glass   env: Adjust the l...
257
  static int env_sf_load(void)
8c66497e0   Haavard Skinnemoen   Add support for e...
258
259
  {
  	int ret;
5a89fa927   Ying Zhang   SPL: P2020RDB: fi...
260
  	char *buf = NULL;
8c66497e0   Haavard Skinnemoen   Add support for e...
261

7dd017446   Ravi Babu   env: use cache li...
262
  	buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE);
c041c60c6   Andreas Fenkart   env_sf: re-order ...
263
264
  	if (!buf) {
  		set_default_env("!malloc() failed");
c59519919   Simon Glass   env: Adjust the l...
265
  		return -EIO;
ea882baf9   Wolfgang Denk   New implementatio...
266
  	}
8c66497e0   Haavard Skinnemoen   Add support for e...
267

c041c60c6   Andreas Fenkart   env_sf: re-order ...
268
269
270
  	ret = setup_flash_device();
  	if (ret)
  		goto out;
ea882baf9   Wolfgang Denk   New implementatio...
271
272
273
274
  	ret = spi_flash_read(env_flash,
  		CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
  	if (ret) {
  		set_default_env("!spi_flash_read() failed");
c041c60c6   Andreas Fenkart   env_sf: re-order ...
275
  		goto err_read;
ea882baf9   Wolfgang Denk   New implementatio...
276
  	}
8c66497e0   Haavard Skinnemoen   Add support for e...
277

ea882baf9   Wolfgang Denk   New implementatio...
278
  	ret = env_import(buf, 1);
42a1820bb   Simon Goldschmidt   env: make env_imp...
279
  	if (!ret)
203e94f6c   Simon Glass   env: Add an enum ...
280
  		gd->env_valid = ENV_VALID;
c041c60c6   Andreas Fenkart   env_sf: re-order ...
281
282
  
  err_read:
8c66497e0   Haavard Skinnemoen   Add support for e...
283
284
  	spi_flash_free(env_flash);
  	env_flash = NULL;
c041c60c6   Andreas Fenkart   env_sf: re-order ...
285
286
  out:
  	free(buf);
c59519919   Simon Glass   env: Adjust the l...
287
288
  
  	return ret;
8c66497e0   Haavard Skinnemoen   Add support for e...
289
  }
7319bcaf8   Wolfgang Wegner   add redundant env...
290
  #endif
8c66497e0   Haavard Skinnemoen   Add support for e...
291

b500c92b7   Ashish Kumar   env: sf: Add supp...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  #if defined(INITENV) && defined(CONFIG_ENV_ADDR)
  static int env_sf_init(void)
  {
  	env_t *env_ptr = (env_t *)(CONFIG_ENV_ADDR);
  
  	if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
  		gd->env_addr	= (ulong)&(env_ptr->data);
  		gd->env_valid	= 1;
  	} else {
  		gd->env_addr = (ulong)&default_environment[0];
  		gd->env_valid = 1;
  	}
  
  	return 0;
  }
  #endif
4415f1d1f   Simon Glass   env: Create a loc...
308
309
  U_BOOT_ENV_LOCATION(sf) = {
  	.location	= ENVL_SPI_FLASH,
ac358beb8   Simon Glass   env: Drop the env...
310
  	ENV_NAME("SPI Flash")
e5bce247b   Simon Glass   env: Switch over ...
311
  	.load		= env_sf_load,
4415f1d1f   Simon Glass   env: Create a loc...
312
  #ifdef CMD_SAVEENV
e5bce247b   Simon Glass   env: Switch over ...
313
  	.save		= env_save_ptr(env_sf_save),
4415f1d1f   Simon Glass   env: Create a loc...
314
  #endif
b500c92b7   Ashish Kumar   env: sf: Add supp...
315
316
317
  #if defined(INITENV) && defined(CONFIG_ENV_ADDR)
  	.init		= env_sf_init,
  #endif
4415f1d1f   Simon Glass   env: Create a loc...
318
  };