BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / shared / nvram / nvram_rw.c
blob61229db72d9422bd3a03e64f04f2ad52db987957
1 /*
2 * NVRAM variable manipulation (direct mapped flash)
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: nvram_rw.c 258972 2011-05-11 08:57:26Z simonk $
21 #include <bcm_cfg.h>
22 #include <typedefs.h>
23 #include <bcmdefs.h>
24 #include <osl.h>
25 #include <bcmutils.h>
26 #include <siutils.h>
27 #include <mipsinc.h>
28 #include <bcmnvram.h>
29 #include <bcmendian.h>
30 #include <flashutl.h>
31 #include <hndsoc.h>
32 #include <sbchipc.h>
34 #ifdef NFLASH_SUPPORT
35 #include <nflash.h>
36 #endif /* NFLASH_SUPPORT */
38 struct nvram_tuple *_nvram_realloc(struct nvram_tuple *t, const char *name, const char *value);
39 void _nvram_free(struct nvram_tuple *t);
40 int _nvram_read(void *buf);
42 extern char *_nvram_get(const char *name);
43 extern int _nvram_set(const char *name, const char *value);
44 extern int _nvram_unset(const char *name);
45 extern int _nvram_getall(char *buf, int count);
46 extern int _nvram_commit(struct nvram_header *header);
47 extern int _nvram_init(void *si);
48 extern void _nvram_exit(void);
50 #ifdef __ECOS
51 extern int kernel_initial;
52 #endif
54 static struct nvram_header *nvram_header = NULL;
55 static int nvram_do_reset = FALSE;
57 #ifdef _CFE_
58 /* For NAND boot, flash0.nvram will be changed to nflash0.nvram */
59 char *flashdrv_nvram = "flash0.nvram";
60 #endif
62 #define NVRAM_LOCK() do {} while (0)
63 #define NVRAM_UNLOCK() do {} while (0)
65 /* Convenience */
66 #define KB * 1024
67 #define MB * 1024 * 1024
69 char *
70 nvram_get(const char *name)
72 char *value;
74 #ifdef __ECOS
75 if (!kernel_initial)
76 return NULL;
77 #endif
79 NVRAM_LOCK();
80 value = _nvram_get(name);
81 NVRAM_UNLOCK();
83 return value;
86 int
87 nvram_getall(char *buf, int count)
89 int ret;
91 NVRAM_LOCK();
92 ret = _nvram_getall(buf, count);
93 NVRAM_UNLOCK();
95 return ret;
98 int
99 BCMINITFN(nvram_set)(const char *name, const char *value)
101 int ret;
103 NVRAM_LOCK();
104 ret = _nvram_set(name, value);
105 NVRAM_UNLOCK();
107 return ret;
111 BCMINITFN(nvram_unset)(const char *name)
113 int ret;
115 NVRAM_LOCK();
116 ret = _nvram_unset(name);
117 NVRAM_UNLOCK();
119 return ret;
123 BCMINITFN(nvram_resetgpio_init)(void *si)
125 char *value;
126 int gpio;
127 si_t *sih;
129 sih = (si_t *)si;
131 value = nvram_get("reset_gpio");
132 if (!value)
133 return -1;
135 gpio = (int) bcm_atoi(value);
136 if (gpio > 31)
137 return -1;
139 /* Setup GPIO input */
140 si_gpioouten(sih, ((uint32) 1 << gpio), 0, GPIO_DRV_PRIORITY);
142 return gpio;
146 BCMINITFN(nvram_reset)(void *si)
148 int gpio;
149 uint msec;
150 si_t * sih = (si_t *)si;
152 if ((gpio = nvram_resetgpio_init((void *)sih)) < 0)
153 return FALSE;
155 /* GPIO reset is asserted low */
156 for (msec = 0; msec < 5000; msec++) {
157 if (si_gpioin(sih) & ((uint32) 1 << gpio))
158 return FALSE;
159 OSL_DELAY(1000);
162 nvram_do_reset = TRUE;
163 return TRUE;
166 extern unsigned char embedded_nvram[];
168 static struct nvram_header *
169 BCMINITFN(find_nvram)(si_t *sih, bool embonly, bool *isemb)
171 struct nvram_header *nvh;
172 uint32 off, lim;
173 uint32 flbase = SI_FLASH2;
174 #ifdef NFLASH_SUPPORT
175 int nandboot = 0;
176 chipcregs_t *cc = NULL;
177 struct nflash *nfl_info;
179 if ((sih->ccrev == 38) && ((sih->chipst & (1 << 4)) != 0)) {
180 flbase = SI_FLASH1;
181 nandboot = 1;
183 #endif /* NFLASH_SUPPORT */
185 if (!embonly) {
186 *isemb = FALSE;
187 #ifdef NFLASH_SUPPORT
188 if (nandboot) {
189 if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX))) {
190 nfl_info = nflash_init(sih, cc);
191 if (nfl_info) {
192 off = nfl_info->blocksize;
193 for (; off < SI_FLASH1_SZ; off += nfl_info->blocksize) {
194 if (nflash_checkbadb(sih, cc, off) != 0)
195 continue;
196 nvh = (struct nvram_header *)KSEG1ADDR(flbase+off);
197 if (nvh->magic == NVRAM_MAGIC)
198 return (nvh);
202 } else
203 #endif /* NFLASH_SUPPORT */
205 lim = SI_FLASH2_SZ;
206 off = FLASH_MIN;
207 while (off <= lim) {
208 nvh = (struct nvram_header *)KSEG1ADDR(flbase + off - NVRAM_SPACE);
209 if (nvh->magic == NVRAM_MAGIC)
210 /* if (nvram_calc_crc(nvh) == (uint8) nvh->crc_ver_init) */{
211 return (nvh);
213 off <<= 1;
216 #ifdef BCMDBG
217 printf("find_nvram: nvram not found, trying embedded nvram next\n");
218 #endif /* BCMDBG */
221 /* Now check embedded nvram */
222 *isemb = TRUE;
223 nvh = (struct nvram_header *)KSEG1ADDR(flbase + (4 * 1024));
224 if (nvh->magic == NVRAM_MAGIC)
225 return (nvh);
226 nvh = (struct nvram_header *)KSEG1ADDR(flbase + 1024);
227 if (nvh->magic == NVRAM_MAGIC)
228 return (nvh);
229 #ifdef _CFE_
230 nvh = (struct nvram_header *)embedded_nvram;
231 if (nvh->magic == NVRAM_MAGIC)
232 return (nvh);
233 #endif
234 printf("find_nvram: no nvram found\n");
235 return (NULL);
239 BCMATTACHFN(nvram_init)(void *si)
241 bool isemb;
242 int ret;
243 si_t *sih;
244 static int nvram_status = -1;
246 #ifdef __ECOS
247 if (!kernel_initial)
248 return 0;
249 #endif
251 /* Check for previous 'restore defaults' condition */
252 if (nvram_status == 1)
253 return 1;
255 /* Check whether nvram already initilized */
256 if (nvram_status == 0 && !nvram_do_reset)
257 return 0;
259 sih = (si_t *)si;
261 /* Restore defaults from embedded NVRAM if button held down */
262 if (nvram_do_reset) {
263 /* Initialize with embedded NVRAM */
264 nvram_header = find_nvram(sih, TRUE, &isemb);
265 ret = _nvram_init(si);
266 if (ret == 0) {
267 nvram_status = 1;
268 return 1;
270 nvram_status = -1;
271 _nvram_exit();
274 /* Find NVRAM */
275 nvram_header = find_nvram(sih, FALSE, &isemb);
276 ret = _nvram_init(si);
277 if (ret == 0) {
278 /* Restore defaults if embedded NVRAM used */
279 if (nvram_header && isemb) {
280 ret = 1;
283 nvram_status = ret;
284 return ret;
288 BCMINITFN(nvram_append)(void *si, char *vars, uint varsz)
290 return 0;
293 void
294 BCMINITFN(nvram_exit)(void *si)
296 si_t *sih;
298 sih = (si_t *)si;
300 _nvram_exit();
304 BCMINITFN(_nvram_read)(void *buf)
306 uint32 *src, *dst;
307 uint i;
309 if (!nvram_header)
310 return -19; /* -ENODEV */
312 src = (uint32 *) nvram_header;
313 dst = (uint32 *) buf;
315 for (i = 0; i < sizeof(struct nvram_header); i += 4)
316 *dst++ = *src++;
318 for (; i < nvram_header->len && i < NVRAM_SPACE; i += 4)
319 *dst++ = ltoh32(*src++);
321 return 0;
324 struct nvram_tuple *
325 BCMINITFN(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value)
327 if (!(t = MALLOC(NULL, sizeof(struct nvram_tuple) + strlen(name) + 1 +
328 strlen(value) + 1))) {
329 printf("_nvram_realloc: our of memory\n");
330 return NULL;
333 /* Copy name */
334 t->name = (char *) &t[1];
335 strcpy(t->name, name);
337 /* Copy value */
338 t->value = t->name + strlen(name) + 1;
339 strcpy(t->value, value);
341 return t;
344 void
345 BCMINITFN(_nvram_free)(struct nvram_tuple *t)
347 if (t)
348 MFREE(NULL, t, sizeof(struct nvram_tuple) + strlen(t->name) + 1 +
349 strlen(t->value) + 1);
353 BCMINITFN(nvram_commit)(void)
355 struct nvram_header *header;
356 int ret;
357 uint32 *src, *dst;
358 uint i;
360 if (!(header = (struct nvram_header *) MALLOC(NULL, NVRAM_SPACE))) {
361 printf("nvram_commit: out of memory\n");
362 return -12; /* -ENOMEM */
365 NVRAM_LOCK();
367 /* Regenerate NVRAM */
368 ret = _nvram_commit(header);
369 if (ret)
370 goto done;
372 src = (uint32 *) &header[1];
373 dst = src;
375 for (i = sizeof(struct nvram_header); i < header->len && i < NVRAM_SPACE; i += 4)
376 *dst++ = htol32(*src++);
378 #ifdef _CFE_
379 if ((ret = cfe_open(flashdrv_nvram)) >= 0) {
380 cfe_writeblk(ret, 0, (unsigned char *) header, header->len);
381 cfe_close(ret);
383 #else
384 if (sysFlashInit(NULL) == 0) {
385 /* set/write invalid MAGIC # (in case writing image fails/is interrupted)
386 * write the NVRAM image to flash(with invalid magic)
387 * set/write valid MAGIC #
389 header->magic = NVRAM_CLEAR_MAGIC;
390 nvWriteChars((unsigned char *)&header->magic, sizeof(header->magic));
392 header->magic = NVRAM_INVALID_MAGIC;
393 nvWrite((unsigned short *) header, NVRAM_SPACE);
395 header->magic = NVRAM_MAGIC;
396 nvWriteChars((unsigned char *)&header->magic, sizeof(header->magic));
398 #endif /* ifdef _CFE_ */
400 done:
401 NVRAM_UNLOCK();
402 MFREE(NULL, header, NVRAM_SPACE);
403 return ret;