1/*
2 * NVRAM variable manipulation (direct mapped flash)
3 *
4 * Copyright 2007, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 * $Id: nvram_rw.c,v 1.1.1.1 2008/10/15 03:31:34 james26_jang Exp $
13 */
14
15#include <typedefs.h>
16#include <bcmdefs.h>
17#include <osl.h>
18#include <bcmutils.h>
19#include <sbutils.h>
20#include <mipsinc.h>
21#include <bcmnvram.h>
22#include <bcmendian.h>
23#include <flashutl.h>
24#include <sbconfig.h>
25#include <sbchipc.h>
26
27struct nvram_tuple * _nvram_realloc(struct nvram_tuple *t, const char *name, const char *value);
28void  _nvram_free(struct nvram_tuple *t);
29int  _nvram_read(void *buf);
30
31extern char *_nvram_get(const char *name);
32extern int _nvram_set(const char *name, const char *value);
33extern int _nvram_unset(const char *name);
34extern int _nvram_getall(char *buf, int count);
35extern int _nvram_commit(struct nvram_header *header);
36extern int _nvram_init(void *sb);
37extern void _nvram_exit(void);
38
39static struct nvram_header *nvram_header = NULL;
40static bool nvram_do_reset = FALSE;
41
42#define NVRAM_LOCK()	do {} while (0)
43#define NVRAM_UNLOCK()	do {} while (0)
44
45/* Convenience */
46#define KB * 1024
47#define MB * 1024 * 1024
48
49char *
50nvram_get(const char *name)
51{
52	char *value;
53
54	NVRAM_LOCK();
55	value = _nvram_get(name);
56	NVRAM_UNLOCK();
57
58	return value;
59}
60
61int
62nvram_getall(char *buf, int count)
63{
64	int ret;
65
66	NVRAM_LOCK();
67	ret = _nvram_getall(buf, count);
68	NVRAM_UNLOCK();
69
70	return ret;
71}
72
73int
74BCMINITFN(nvram_set)(const char *name, const char *value)
75{
76	int ret;
77
78	NVRAM_LOCK();
79	ret = _nvram_set(name, value);
80	NVRAM_UNLOCK();
81
82	return ret;
83}
84
85int
86BCMINITFN(nvram_unset)(const char *name)
87{
88	int ret;
89
90	NVRAM_LOCK();
91	ret = _nvram_unset(name);
92	NVRAM_UNLOCK();
93
94	return ret;
95}
96
97int
98BCMINITFN(nvram_resetgpio_init)(void *sb)
99{
100	char *value;
101	int gpio;
102	sb_t *sbh;
103
104	sbh = (sb_t *)sb;
105
106	value = nvram_get("reset_gpio");
107	if (!value)
108		return -1;
109
110	gpio = (int) bcm_atoi(value);
111	if (gpio > 7)
112		return -1;
113
114	/* Setup GPIO input */
115	sb_gpioouten(sbh, ((uint32) 1 << gpio), 0, GPIO_DRV_PRIORITY);
116
117	return gpio;
118}
119
120bool
121BCMINITFN(nvram_reset)(void  *sb)
122{
123	int gpio;
124	uint msec;
125	sb_t * sbh = (sb_t *)sb;
126
127	if ((gpio = nvram_resetgpio_init((void *)sbh)) < 0)
128		return FALSE;
129
130	/* GPIO reset is asserted low */
131	for (msec = 0; msec < 5000; msec++) {
132		if (sb_gpioin(sbh) & ((uint32) 1 << gpio))
133			return FALSE;
134		OSL_DELAY(1000);
135	}
136
137	nvram_do_reset = TRUE;
138	return TRUE;
139}
140
141extern unsigned char embedded_nvram[];
142
143static struct nvram_header *
144BCMINITFN(find_nvram)(bool embonly, bool *isemb)
145{
146	struct nvram_header *nvh;
147	uint32 off, lim;
148
149
150	if (!embonly) {
151		*isemb = FALSE;
152		lim = SB_FLASH2_SZ;
153		off = FLASH_MIN;
154		while (off <= lim) {
155			nvh = (struct nvram_header *)KSEG1ADDR(SB_FLASH2 + off - NVRAM_SPACE);
156			if (nvh->magic == NVRAM_MAGIC)
157				/* if (nvram_calc_crc(nvh) == (uint8) nvh->crc_ver_init) */{
158					return (nvh);
159				}
160			off <<= 1;
161		};
162	}
163
164	/* Now check embedded nvram */
165	*isemb = TRUE;
166	nvh = (struct nvram_header *)KSEG1ADDR(SB_FLASH2 + (4 * 1024));
167	if (nvh->magic == NVRAM_MAGIC)
168		return (nvh);
169	nvh = (struct nvram_header *)KSEG1ADDR(SB_FLASH2 + 1024);
170	if (nvh->magic == NVRAM_MAGIC)
171		return (nvh);
172#ifdef _CFE_
173	nvh = (struct nvram_header *)embedded_nvram;
174	if (nvh->magic == NVRAM_MAGIC)
175		return (nvh);
176#endif
177	printf("find_nvram: no nvram found\n");
178	return (NULL);
179}
180
181int
182BCMINITFN(nvram_init)(void *sb)
183{
184	bool isemb;
185	int ret;
186	sb_t *sbh;
187	static int nvram_status = -1;
188
189	/* Check for previous 'restore defaults' condition */
190	if (nvram_status == 1)
191		return 1;
192
193	/* Check whether nvram already initilized */
194	if (nvram_status == 0 && !nvram_do_reset)
195		return 0;
196
197	sbh = (sb_t *)sb;
198
199	/* Restore defaults from embedded NVRAM if button held down */
200	if (nvram_do_reset) {
201		/* Initialize with embedded NVRAM */
202		nvram_header = find_nvram(TRUE, &isemb);
203		ret = _nvram_init(sb);
204		if (ret == 0) {
205			nvram_status = 1;
206			return 1;
207		}
208		nvram_status = -1;
209		_nvram_exit();
210	}
211
212	/* Find NVRAM */
213	nvram_header = find_nvram(FALSE, &isemb);
214	ret = _nvram_init(sb);
215	if (ret == 0) {
216		/* Restore defaults if embedded NVRAM used */
217		if (nvram_header && isemb) {
218			ret = 1;
219		}
220	}
221	nvram_status = ret;
222	return ret;
223}
224
225int
226BCMINITFN(nvram_append)(void *sb, char *vars, uint varsz)
227{
228	return 0;
229}
230
231void
232BCMINITFN(nvram_exit)(void *sb)
233{
234	sb_t *sbh;
235
236	sbh = (sb_t *)sb;
237
238	_nvram_exit();
239}
240
241int
242BCMINITFN(_nvram_read)(void *buf)
243{
244	uint32 *src, *dst;
245	uint i;
246
247	if (!nvram_header)
248		return -19; /* -ENODEV */
249
250	src = (uint32 *) nvram_header;
251	dst = (uint32 *) buf;
252
253	for (i = 0; i < sizeof(struct nvram_header); i += 4)
254		*dst++ = *src++;
255
256	for (; i < nvram_header->len && i < NVRAM_SPACE; i += 4)
257		*dst++ = ltoh32(*src++);
258
259	return 0;
260}
261
262struct nvram_tuple *
263BCMINITFN(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value)
264{
265	if (!(t = MALLOC(NULL, sizeof(struct nvram_tuple) + strlen(name) + 1 +
266	                 strlen(value) + 1))) {
267		printf("_nvram_realloc: our of memory\n");
268		return NULL;
269	}
270
271	/* Copy name */
272	t->name = (char *) &t[1];
273	strcpy(t->name, name);
274
275	/* Copy value */
276	t->value = t->name + strlen(name) + 1;
277	strcpy(t->value, value);
278
279	return t;
280}
281
282void
283BCMINITFN(_nvram_free)(struct nvram_tuple *t)
284{
285	if (t)
286		MFREE(NULL, t, sizeof(struct nvram_tuple) + strlen(t->name) + 1 +
287		      strlen(t->value) + 1);
288}
289
290int
291BCMINITFN(nvram_commit)(void)
292{
293	struct nvram_header *header;
294	int ret;
295	uint32 *src, *dst;
296	uint i;
297
298	if (!(header = (struct nvram_header *) MALLOC(NULL, NVRAM_SPACE))) {
299		printf("nvram_commit: out of memory\n");
300		return -12; /* -ENOMEM */
301	}
302
303	NVRAM_LOCK();
304
305	/* Regenerate NVRAM */
306	ret = _nvram_commit(header);
307	if (ret)
308		goto done;
309
310	src = (uint32 *) &header[1];
311	dst = src;
312
313	for (i = sizeof(struct nvram_header); i < header->len && i < NVRAM_SPACE; i += 4)
314		*dst++ = htol32(*src++);
315
316#ifdef _CFE_
317	if ((ret = cfe_open("flash0.nvram")) >= 0) {
318		cfe_writeblk(ret, 0, (unsigned char *) header, header->len);
319		cfe_close(ret);
320	}
321#else
322	if (sysFlashInit(NULL) == 0) {
323		/* set/write invalid MAGIC # (in case writing image fails/is interrupted)
324			 write the NVRAM image to flash(with invalid magic)
325			 set/write valid MAGIC #
326		*/
327		header->magic = NVRAM_CLEAR_MAGIC;
328		nvWriteChars((unsigned char *)&header->magic, sizeof(header->magic));
329
330		header->magic = NVRAM_INVALID_MAGIC;
331		nvWrite((unsigned short *) header, NVRAM_SPACE);
332
333		header->magic = NVRAM_MAGIC;
334		nvWriteChars((unsigned char *)&header->magic, sizeof(header->magic));
335	}
336#endif /* ifdef _CFE_ */
337
338done:
339	NVRAM_UNLOCK();
340	MFREE(NULL, header, NVRAM_SPACE);
341	return ret;
342}
343