Commit 1567b596d9f4a7ff49ebdca29e15a33777dfd670

Authored by Heiko Schocher
Committed by Wolfgang Denk
1 parent 548738b4d4

env, eeprom: add redundant environment support

Add redundant environment support for environment lying on a EEPROM.

Tested on uppcoming suen3 support

Signed-off-by: Andreas Huber <andreas.huber@keymile.com>

Showing 1 changed file with 127 additions and 4 deletions Side-by-side Diff

... ... @@ -32,6 +32,11 @@
32 32 #include <i2c.h>
33 33 #endif
34 34  
  35 +#ifdef CONFIG_ENV_OFFSET_REDUND
  36 +#define ACTIVE_FLAG 1
  37 +#define OBSOLETE_FLAG 0
  38 +#endif
  39 +
35 40 DECLARE_GLOBAL_DATA_PTR;
36 41  
37 42 env_t *env_ptr = NULL;
38 43  
... ... @@ -93,9 +98,15 @@
93 98 uchar env_get_char_spec (int index)
94 99 {
95 100 uchar c;
  101 + unsigned int off;
  102 + off = CONFIG_ENV_OFFSET;
  103 +#ifdef CONFIG_ENV_OFFSET_REDUND
  104 + if (gd->env_valid == 2)
  105 + off = CONFIG_ENV_OFFSET_REDUND;
  106 +#endif
96 107  
97 108 eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR,
98   - CONFIG_ENV_OFFSET+index+offsetof(env_t,data),
  109 + off + index + offsetof(env_t,data),
99 110 &c, 1);
100 111  
101 112 return (c);
102 113  
103 114  
104 115  
... ... @@ -103,18 +114,52 @@
103 114  
104 115 void env_relocate_spec (void)
105 116 {
  117 + unsigned int off = CONFIG_ENV_OFFSET;
  118 +#ifdef CONFIG_ENV_OFFSET_REDUND
  119 + if (gd->env_valid == 2)
  120 + off = CONFIG_ENV_OFFSET_REDUND;
  121 +#endif
106 122 eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR,
107   - CONFIG_ENV_OFFSET,
  123 + off,
108 124 (uchar*)env_ptr,
109 125 CONFIG_ENV_SIZE);
110 126 }
111 127  
112 128 int saveenv(void)
113 129 {
114   - return eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR,
115   - CONFIG_ENV_OFFSET,
  130 + int rc;
  131 + unsigned int off = CONFIG_ENV_OFFSET;
  132 +#ifdef CONFIG_ENV_OFFSET_REDUND
  133 + unsigned int off_red = CONFIG_ENV_OFFSET_REDUND;
  134 + char flag_obsolete = OBSOLETE_FLAG;
  135 + if (gd->env_valid == 1) {
  136 + off = CONFIG_ENV_OFFSET_REDUND;
  137 + off_red = CONFIG_ENV_OFFSET;
  138 + }
  139 +
  140 + env_ptr->flags = ACTIVE_FLAG;
  141 +#endif
  142 +
  143 + rc = eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR,
  144 + off,
116 145 (uchar *)env_ptr,
117 146 CONFIG_ENV_SIZE);
  147 +
  148 +#ifdef CONFIG_ENV_OFFSET_REDUND
  149 + if (rc == 0) {
  150 + eeprom_bus_write (CONFIG_SYS_DEF_EEPROM_ADDR,
  151 + off_red + offsetof(env_t,flags),
  152 + (uchar *)&flag_obsolete,
  153 + 1);
  154 + if (gd->env_valid == 1)
  155 + gd->env_valid = 2;
  156 + else
  157 + gd->env_valid = 1;
  158 +
  159 + }
  160 +#endif
  161 +
  162 + return rc;
118 163 }
119 164  
120 165 /************************************************************************
121 166  
... ... @@ -123,8 +168,84 @@
123 168 * We are still running from ROM, so data use is limited
124 169 * Use a (moderately small) buffer on the stack
125 170 */
  171 +
  172 +#ifdef CONFIG_ENV_OFFSET_REDUND
126 173 int env_init(void)
127 174 {
  175 + ulong len;
  176 + ulong crc[2], crc_tmp;
  177 + unsigned int off, off_env[2];
  178 + uchar buf[64];
  179 + int crc_ok[2] = {0,0};
  180 + unsigned char flags[2];
  181 + int i;
  182 +
  183 + eeprom_init (); /* prepare for EEPROM read/write */
  184 +
  185 + off_env[0] = CONFIG_ENV_OFFSET;
  186 + off_env[1] = CONFIG_ENV_OFFSET_REDUND;
  187 +
  188 + for (i = 0; i < 2; i++) {
  189 + /* read CRC */
  190 + eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR,
  191 + off_env[i] + offsetof(env_t,crc),
  192 + (uchar *)&crc[i], sizeof(ulong));
  193 + /* read FLAGS */
  194 + eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR,
  195 + off_env[i] + offsetof(env_t,flags),
  196 + (uchar *)&flags[i], sizeof(uchar));
  197 +
  198 + crc_tmp= 0;
  199 + len = ENV_SIZE;
  200 + off = off_env[i] + offsetof(env_t,data);
  201 + while (len > 0) {
  202 + int n = (len > sizeof(buf)) ? sizeof(buf) : len;
  203 +
  204 + eeprom_bus_read (CONFIG_SYS_DEF_EEPROM_ADDR, off,
  205 + buf, n);
  206 +
  207 + crc_tmp = crc32 (crc_tmp, buf, n);
  208 + len -= n;
  209 + off += n;
  210 + }
  211 + if (crc_tmp == crc[i])
  212 + crc_ok[i] = 1;
  213 + }
  214 +
  215 + if (!crc_ok[0] && !crc_ok[1]) {
  216 + gd->env_addr = 0;
  217 + gd->env_valid = 0;
  218 +
  219 + return 0;
  220 + } else if (crc_ok[0] && !crc_ok[1]) {
  221 + gd->env_valid = 1;
  222 + }
  223 + else if (!crc_ok[0] && crc_ok[1]) {
  224 + gd->env_valid = 2;
  225 + } else {
  226 + /* both ok - check serial */
  227 + if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG)
  228 + gd->env_valid = 1;
  229 + else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG)
  230 + gd->env_valid = 2;
  231 + else if (flags[0] == 0xFF && flags[1] == 0)
  232 + gd->env_valid = 2;
  233 + else if(flags[1] == 0xFF && flags[0] == 0)
  234 + gd->env_valid = 1;
  235 + else /* flags are equal - almost impossible */
  236 + gd->env_valid = 1;
  237 + }
  238 +
  239 + if (gd->env_valid == 2)
  240 + gd->env_addr = off_env[1] + offsetof(env_t,data);
  241 + else if (gd->env_valid == 1)
  242 + gd->env_addr = off_env[0] + offsetof(env_t,data);
  243 +
  244 + return (0);
  245 +}
  246 +#else
  247 +int env_init(void)
  248 +{
128 249 ulong crc, len, new;
129 250 unsigned off;
130 251 uchar buf[64];
... ... @@ -159,4 +280,5 @@
159 280  
160 281 return (0);
161 282 }
  283 +#endif