X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Fbrcm-2.4%2Ffiles%2Farch%2Fmips%2Fbcm947xx%2Fnvram.c;fp=target%2Flinux%2Fbrcm-2.4%2Ffiles%2Farch%2Fmips%2Fbcm947xx%2Fnvram.c;h=e93752a373b5d5a0816b3ccd786d0cb6a1345ed1;hb=9c689fb0002dd622ccecd418598ef3fd51e73290;hp=c37023bce7cb8519c14d8fe3c314bac5d09b0ab1;hpb=0b2956f22017f93b7e1f8ee44355ef9b92bba69f;p=openwrt%2Fsvn-archive%2Farchive.git diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c index c37023bce7..e93752a373 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c @@ -1,7 +1,7 @@ /* - * NVRAM variable manipulation (common) + * NVRAM variable manipulation (Linux kernel half) * - * Copyright 2004, Broadcom Corporation + * Copyright 2006, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -11,306 +11,203 @@ * */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include #include -#include - -extern struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value); -extern void BCMINIT(_nvram_free)(struct nvram_tuple *t); -extern int BCMINIT(_nvram_read)(void *buf); - -char * BCMINIT(_nvram_get)(const char *name); -int BCMINIT(_nvram_set)(const char *name, const char *value); -int BCMINIT(_nvram_unset)(const char *name); -int BCMINIT(_nvram_getall)(char *buf, int count); -int BCMINIT(_nvram_commit)(struct nvram_header *header); -int BCMINIT(_nvram_init)(void); -void BCMINIT(_nvram_exit)(void); - -static struct nvram_tuple * BCMINITDATA(nvram_hash)[257]; -static struct nvram_tuple * nvram_dead; - -/* Free all tuples. Should be locked. */ -static void -BCMINITFN(nvram_free)(void) -{ - uint i; - struct nvram_tuple *t, *next; - - /* Free hash table */ - for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { - for (t = BCMINIT(nvram_hash)[i]; t; t = next) { - next = t->next; - BCMINIT(_nvram_free)(t); - } - BCMINIT(nvram_hash)[i] = NULL; - } +#include +#include +#include +#include +#include - /* Free dead table */ - for (t = nvram_dead; t; t = next) { - next = t->next; - BCMINIT(_nvram_free)(t); - } - nvram_dead = NULL; +/* In BSS to minimize text size and page aligned so it can be mmap()-ed */ +static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE))); - /* Indicate to per-port code that all tuples have been freed */ - BCMINIT(_nvram_free)(NULL); -} +/* Global SB handle */ +extern void *bcm947xx_sbh; +extern spinlock_t bcm947xx_sbh_lock; -/* String hash */ -static INLINE uint -hash(const char *s) -{ - uint hash = 0; - - while (*s) - hash = 31 * hash + *s++; +static int cfe_env; +extern char *cfe_env_get(char *nv_buf, const char *name); - return hash; -} +/* Convenience */ +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock -/* (Re)initialize the hash table. Should be locked. */ -static int -BCMINITFN(nvram_rehash)(struct nvram_header *header) +/* Probe for NVRAM header */ +static void __init +early_nvram_init(void) { - char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq; - - /* (Re)initialize hash table */ - BCMINIT(nvram_free)(); + struct nvram_header *header; + chipcregs_t *cc; + struct sflash *info = NULL; + int i; + uint32 base, off, lim; + u32 *src, *dst; + + if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { + base = KSEG1ADDR(SB_FLASH2); + switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) { + case PFLASH: + lim = SB_FLASH2_SZ; + break; - /* Parse and set "name=value\0 ... \0\0" */ - name = (char *) &header[1]; - end = (char *) header + NVRAM_SPACE - 2; - end[0] = end[1] = '\0'; - for (; *name; name = value + strlen(value) + 1) { - if (!(eq = strchr(name, '='))) + case SFLASH_ST: + case SFLASH_AT: + if ((info = sflash_init(sbh,cc)) == NULL) + return; + lim = info->size; break; - *eq = '\0'; - value = eq + 1; - BCMINIT(_nvram_set)(name, value); - *eq = '='; - } - /* Set special SDRAM parameters */ - if (!BCMINIT(_nvram_get)("sdram_init")) { - sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16)); - BCMINIT(_nvram_set)("sdram_init", buf); - } - if (!BCMINIT(_nvram_get)("sdram_config")) { - sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff)); - BCMINIT(_nvram_set)("sdram_config", buf); - } - if (!BCMINIT(_nvram_get)("sdram_refresh")) { - sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff)); - BCMINIT(_nvram_set)("sdram_refresh", buf); - } - if (!BCMINIT(_nvram_get)("sdram_ncdl")) { - sprintf(buf, "0x%08X", header->config_ncdl); - BCMINIT(_nvram_set)("sdram_ncdl", buf); + case FLASH_NONE: + default: + return; + } + } else { + /* extif assumed, Stop at 4 MB */ + base = KSEG1ADDR(SB_FLASH1); + lim = SB_FLASH1_SZ; } - return 0; -} - -/* Get the value of an NVRAM variable. Should be locked. */ -char * -BCMINITFN(_nvram_get)(const char *name) -{ - uint i; - struct nvram_tuple *t; - char *value; - - if (!name) - return NULL; - - /* Hash the name */ - i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); - - /* Find the associated tuple in the hash table */ - for (t = BCMINIT(nvram_hash)[i]; t && strcmp(t->name, name); t = t->next); - - value = t ? t->value : NULL; + /* XXX: hack for supporting the CFE environment stuff on WGT634U */ + src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000); + dst = (u32 *) nvram_buf; + if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) { + printk("early_nvram_init: WGT634U NVRAM found.\n"); - return value; -} - -/* Get the value of an NVRAM variable. Should be locked. */ -int -BCMINITFN(_nvram_set)(const char *name, const char *value) -{ - uint i; - struct nvram_tuple *t, *u, **prev; - - /* Hash the name */ - i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); - - /* Find the associated tuple in the hash table */ - for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev); - - /* (Re)allocate tuple */ - if (!(u = BCMINIT(_nvram_realloc)(t, name, value))) - return -12; /* -ENOMEM */ - - /* Value reallocated */ - if (t && t == u) - return 0; - - /* Move old tuple to the dead table */ - if (t) { - *prev = t->next; - t->next = nvram_dead; - nvram_dead = t; + for (i = 0; i < 0x1ff0; i++) { + if (*src == 0xFFFFFFFF) + break; + *dst++ = *src++; + } + cfe_env = 1; + return; } - /* Add new tuple to the hash table */ - u->next = BCMINIT(nvram_hash)[i]; - BCMINIT(nvram_hash)[i] = u; + off = FLASH_MIN; + while (off <= lim) { + /* Windowed flash access */ + header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); + if (header->magic == NVRAM_MAGIC) + goto found; + off <<= 1; + } - return 0; + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ + header = (struct nvram_header *) KSEG1ADDR(base + 4 * 1024); + if (header->magic == NVRAM_MAGIC) + goto found; + + header = (struct nvram_header *) KSEG1ADDR(base + 1 * 1024); + if (header->magic == NVRAM_MAGIC) + goto found; + + printk("early_nvram_init: NVRAM not found\n"); + return; + +found: + src = (u32 *) header; + dst = (u32 *) nvram_buf; + for (i = 0; i < sizeof(struct nvram_header); i += 4) + *dst++ = *src++; + for (; i < header->len && i < NVRAM_SPACE; i += 4) + *dst++ = ltoh32(*src++); } -/* Unset the value of an NVRAM variable. Should be locked. */ -int -BCMINITFN(_nvram_unset)(const char *name) +/* Early (before mm or mtd) read-only access to NVRAM */ +static char * __init +early_nvram_get(const char *name) { - uint i; - struct nvram_tuple *t, **prev; + char *var, *value, *end, *eq; if (!name) - return 0; + return NULL; + + /* Too early? */ + if (sbh == NULL) + return NULL; - /* Hash the name */ - i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); + if (!nvram_buf[0]) + early_nvram_init(); - /* Find the associated tuple in the hash table */ - for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev); + if (cfe_env) + return cfe_env_get(nvram_buf, name); - /* Move it to the dead table */ - if (t) { - *prev = t->next; - t->next = nvram_dead; - nvram_dead = t; + /* Look for name=value and return value */ + var = &nvram_buf[sizeof(struct nvram_header)]; + end = nvram_buf + sizeof(nvram_buf) - 2; + end[0] = end[1] = '\0'; + for (; *var; var = value + strlen(value) + 1) { + if (!(eq = strchr(var, '='))) + break; + value = eq + 1; + if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0) + return value; } - return 0; + return NULL; } -/* Get all NVRAM variables. Should be locked. */ -int -BCMINITFN(_nvram_getall)(char *buf, int count) +static int __init +early_nvram_getall(char *buf, int count) { - uint i; - struct nvram_tuple *t; + char *var, *end; int len = 0; + + /* Too early? */ + if (sbh == NULL) + return -1; + + if (!nvram_buf[0]) + early_nvram_init(); bzero(buf, count); /* Write name=value\0 ... \0\0 */ - for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { - for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) { - if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1)) - len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1; - else - break; - } + var = &nvram_buf[sizeof(struct nvram_header)]; + end = nvram_buf + sizeof(nvram_buf) - 2; + end[0] = end[1] = '\0'; + for (; *var; var += strlen(var) + 1) { + if ((count - len) <= (strlen(var) + 1)) + break; + len += sprintf(buf + len, "%s", var) + 1; } return 0; } -/* Regenerate NVRAM. Should be locked. */ -int -BCMINITFN(_nvram_commit)(struct nvram_header *header) -{ - char *init, *config, *refresh, *ncdl; - char *ptr, *end; - int i; - struct nvram_tuple *t; - struct nvram_header tmp; - uint8 crc; - - /* Regenerate header */ - header->magic = NVRAM_MAGIC; - header->crc_ver_init = (NVRAM_VERSION << 8); - if (!(init = BCMINIT(_nvram_get)("sdram_init")) || - !(config = BCMINIT(_nvram_get)("sdram_config")) || - !(refresh = BCMINIT(_nvram_get)("sdram_refresh")) || - !(ncdl = BCMINIT(_nvram_get)("sdram_ncdl"))) { - header->crc_ver_init |= SDRAM_INIT << 16; - header->config_refresh = SDRAM_CONFIG; - header->config_refresh |= SDRAM_REFRESH << 16; - header->config_ncdl = 0; - } else { - header->crc_ver_init |= (simple_strtoul(init, NULL, 0) & 0xffff) << 16; - header->config_refresh = simple_strtoul(config, NULL, 0) & 0xffff; - header->config_refresh |= (simple_strtoul(refresh, NULL, 0) & 0xffff) << 16; - header->config_ncdl = simple_strtoul(ncdl, NULL, 0); - } - - /* Clear data area */ - ptr = (char *) header + sizeof(struct nvram_header); - bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header)); - /* Leave space for a double NUL at the end */ - end = (char *) header + NVRAM_SPACE - 2; - - /* Write out all tuples */ - for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { - for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) { - if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end) - break; - ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1; - } - } - - /* End with a double NUL */ - ptr += 2; - - /* Set new length */ - header->len = ROUNDUP(ptr - (char *) header, 4); - - /* Little-endian CRC8 over the last 11 bytes of the header */ - tmp.crc_ver_init = htol32(header->crc_ver_init); - tmp.config_refresh = htol32(header->config_refresh); - tmp.config_ncdl = htol32(header->config_ncdl); - crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, 0xff); - - /* Continue CRC8 over data bytes */ - crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc); - - /* Set new CRC8 */ - header->crc_ver_init |= crc; - - /* Reinitialize hash table */ - return BCMINIT(nvram_rehash)(header); +char * +nvram_get(const char *name) +{ + return early_nvram_get(name); } -/* Initialize hash table. Should be locked. */ -int -BCMINITFN(_nvram_init)(void) +int +nvram_getall(char *buf, int count) { - struct nvram_header *header; + unsigned long flags; int ret; - if (!(header = (struct nvram_header *) kmalloc(NVRAM_SPACE, GFP_ATOMIC))) { - return -12; /* -ENOMEM */ - } - - if ((ret = BCMINIT(_nvram_read)(header)) == 0 && - header->magic == NVRAM_MAGIC) - BCMINIT(nvram_rehash)(header); - - kfree(header); - return ret; -} - -/* Free hash table. Should be locked. */ -void -BCMINITFN(_nvram_exit)(void) -{ - BCMINIT(nvram_free)(); + return early_nvram_getall(buf, count); } /* @@ -331,8 +228,7 @@ getvar(char *vars, const char *name) if ((memcmp(s, name, len) == 0) && (s[len] == '=')) return (&s[len+1]); - while (*s++) - ; + while (*s++); } /* then query nvram */ @@ -354,4 +250,3 @@ getintvar(char *vars, const char *name) return (simple_strtoul(val, NULL, 0)); } -