aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/u-boot/u-boot-2009.11/at91/0008-env_dataflash.c-More-robust-handling.patch
blob: 7c38c0c7c09739fa1e6b996a201e71adba177785 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
From 50edf2024c826048652f29a350887946fba4a509 Mon Sep 17 00:00:00 2001
From: Ulf Samuelsson <ulf.samuelsson@atmel.com>
Date: Sat, 13 Mar 2010 23:56:39 +0100
Subject: [PATCH] env_dataflash.c: More robust handling.

1: When u-boot environment is in dataflash, it is safe to
   assume that this is the boot flash.
   We can then assume we are already reloacted to DRAM
   and have plenty of memory.
   No need to split reads into inefficient small chunks
2: Reread memory on CRC error
3: Validate writes to environment, and repeat.

Signed-off-by: Ulf Samuelsson <ulf.samuelsson@atmel.com>
---
 common/env_dataflash.c |   85 +++++++++++++++++++++++++++++++----------------
 1 files changed, 56 insertions(+), 29 deletions(-)

diff --git a/common/env_dataflash.c b/common/env_dataflash.c
index 27a3bbc..a394baa 100644
--- a/common/env_dataflash.c
+++ b/common/env_dataflash.c
@@ -23,11 +23,18 @@
 #include <linux/stddef.h>
 #include <dataflash.h>
 
+#ifdef DEBUG
+#define pr_debug(fmt, args...) printf(fmt, ##args)
+#else
+#define pr_debug(...) do { } while(0)
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 env_t *env_ptr = NULL;
 
 char * env_name_spec = "dataflash";
+static	env_t	buf;
 
 extern int read_dataflash (unsigned long addr, unsigned long size, char
 *result);
@@ -45,54 +52,74 @@ uchar env_get_char_spec (int index)
 	return (c);
 }
 
+
 void env_relocate_spec (void)
 {
-	read_dataflash(CONFIG_ENV_ADDR, CONFIG_ENV_SIZE, (char *)env_ptr);
+	ulong	new;
+	ulong	i;
+	for(i = 0; i < 320; i++) {
+		read_dataflash(CONFIG_ENV_ADDR,sizeof(env_t), (char *)&buf);
+		new = crc32 (0, buf.data, sizeof(buf.data));
+		pr_debug("Stored CRC=[0x%08x], Read CRC=[0x%08x]\r\n",buf.crc,new);
+		if(new == buf.crc) {
+			pr_debug ("*** CRC in dataflash valid\n\n");
+			gd->env_addr  = offsetof(env_t,data);
+			gd->env_valid = 1;
+			env_ptr = &buf;
+			return;
+		}
+	}
 }
 
 int saveenv(void)
 {
 	/* env must be copied to do not alter env structure in memory*/
+	int	error;
+	int	i;
 	unsigned char temp[CONFIG_ENV_SIZE];
-	memcpy(temp, env_ptr, CONFIG_ENV_SIZE);
-	return write_dataflash(CONFIG_ENV_ADDR, (unsigned long)temp, CONFIG_ENV_SIZE);
+
+	for(i = 0; i < 4; i++) {
+		memcpy(temp, env_ptr, CONFIG_ENV_SIZE);
+		error = write_dataflash(CONFIG_ENV_ADDR, (unsigned long)temp, CONFIG_ENV_SIZE);
+		read_dataflash(CONFIG_ENV_ADDR,sizeof(env_t), (char *)&temp);
+		if (memcmp(env_ptr,temp,CONFIG_ENV_SIZE) == 0) return error;
+		pr_debug("Dataflash environment verify failed, retrying...\n");
+	}
+	pr_debug("Dataflash environment verify failed, aborting...\n");
+	return error;
 }
 
 /************************************************************************
  * Initialize Environment use
- *
- * We are still running from ROM, so data use is limited
- * Use a (moderately small) buffer on the stack
+ * When environment is in dataflash, it is OK to assume that we
+ * are booting from dataflash, and then u-boot is always executing 
+ * from DRAM. Use a large buffer for faster/easier use
  */
 int env_init(void)
 {
-	ulong crc, len, new;
-	unsigned off;
-	uchar buf[64];
+	unsigned int crc,  new;
+	int	i;
 	if (gd->env_valid == 0){
 		AT91F_DataflashInit();	/* prepare for DATAFLASH read/write */
+		for(i = 0; i < 24; i++) {
+			read_dataflash(CONFIG_ENV_ADDR,sizeof(env_t), (char *)&buf);
+			new = crc32 (0, buf.data, sizeof(buf.data));
+			pr_debug("Stored CRC=[0x%08x], Read CRC=[0x%08x]\r\n",buf.crc,new);
+			if(new == buf.crc) {
+				pr_debug ("*** CRC in dataflash valid\n");
+				gd->env_addr  = offsetof(env_t,data);
+				gd->env_valid = 1;
+				return 0;
 
-		/* read old CRC */
-		read_dataflash(CONFIG_ENV_ADDR + offsetof(env_t, crc),
-			sizeof(ulong), (char *)&crc);
-		new = 0;
-		len = ENV_SIZE;
-		off = offsetof(env_t,data);
-		while (len > 0) {
-			int n = (len > sizeof(buf)) ? sizeof(buf) : len;
-			read_dataflash(CONFIG_ENV_ADDR + off, n, (char *)buf);
-			new = crc32 (new, buf, n);
-			len -= n;
-			off += n;
-		}
-		if (crc == new) {
-			gd->env_addr  = offsetof(env_t,data);
-			gd->env_valid = 1;
-		} else {
-			gd->env_addr  = (ulong)&default_environment[0];
-			gd->env_valid = 0;
+			}
 		}
+		pr_debug("*** CRC in dataflash not valid\n\n");
+		pr_debug("Stored CRC=[0x%08x], Read CRC=[0x%08x]\r\n",crc,new);
+		pr_debug("Buffer = [0x%08x]\n\n\r", (unsigned int) &buf);
+		pr_debug("Default = [0x%08x]\n\n\r", (unsigned int) default_environment);
+		pr_debug("Environment = [0x%08x]\n\n\r", (unsigned int) env_ptr);
+		gd->env_addr  = (ulong)&default_environment[0];
+		gd->env_valid = 0;
 	}
-
 	return (0);
 }
-- 
1.6.0.2