--- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -20,11 +20,12 @@ #include #include #include +#include static char nvram_buf[NVRAM_SPACE]; /* Probe for NVRAM header */ -static void early_nvram_init(void) +static void early_nvram_init_pflash(void) { #ifdef CONFIG_BCM47XX_SSB struct ssb_chipcommon *ssb_cc; @@ -50,9 +51,6 @@ static void early_nvram_init(void) #ifdef CONFIG_BCM47XX_BCMA case BCM47XX_BUS_TYPE_BCMA: bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc; - if (bcma_cc->flash_type != BCMA_PFLASH) - return; - base = bcma_cc->pflash.window; lim = bcma_cc->pflash.window_size; break; @@ -86,7 +84,115 @@ found: for (i = 0; i < sizeof(struct nvram_header); i += 4) *dst++ = *src++; for (; i < header->len && i < NVRAM_SPACE; i += 4) - *dst++ = le32_to_cpu(*src++); + *dst++ = *src++; +} + +static int find_nvram_size(void) +{ + struct nvram_header header; + int nvram_sizes[] = {NVRAM_SPACE, 0xF000, 2 * NVRAM_SPACE}; + int i; + int ret; + + for (i = 0; i < sizeof(nvram_sizes); i++) { + ret = bcm47xx_sflash.read(&bcm47xx_sflash, bcm47xx_sflash.size - nvram_sizes[i], sizeof(header), (u8 *)&header); + if (ret != sizeof(header)) + return ret; + if (header.magic == NVRAM_HEADER) + return nvram_sizes[i]; + } + return -1; +} + +static int early_nvram_init_sflash(void) +{ + u32 off; + int ret; + char *dst; + int len; + int size; + + /* check if the struct is already initilized */ + if (!bcm47xx_sflash.size) + return -1; + + size = find_nvram_size(); + if (size <= 0) + return size; + + len = NVRAM_SPACE; + dst = nvram_buf; + off = bcm47xx_sflash.size; + if (size > len) { + printk(KERN_WARNING "nvram on flash is bigger than the reserved" + " space in memory, will just copy the first %i bytes\n", + len); + } + while (len) { + ret = bcm47xx_sflash.read(&bcm47xx_sflash, off - size, len, dst); + if (ret < 0) + return ret; + off += ret; + len -= ret; + dst += ret; + } + return 0; +} + +#ifdef CONFIG_BCM47XX_SSB +static void early_nvram_init_ssb(void) +{ + int err; + + switch (bcm47xx_bus.ssb.chipco.flash_type) { + case SSB_PFLASH: + early_nvram_init_pflash(); + break; + case SSB_SFLASH: + err = early_nvram_init_sflash(); + if (err < 0) + printk(KERN_WARNING "can not read from flash: %i\n", err); + break; + default: + printk(KERN_WARNING "unknow flash type\n"); + } +} +#endif + +#ifdef CONFIG_BCM47XX_BCMA +static void early_nvram_init_bcma(void) +{ + int err; + + switch (bcm47xx_bus.bcma.bus.drv_cc.flash_type) { + case BCMA_PFLASH: + early_nvram_init_pflash(); + break; + case BCMA_SFLASH: + err = early_nvram_init_sflash(); + if (err < 0) + printk(KERN_WARNING "can not read from flash: %i\n", err); + break; + default: + printk(KERN_WARNING "unknow flash type\n"); + } +} +#endif + +static void early_nvram_init(void) +{ + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + early_nvram_init_ssb(); + break; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + early_nvram_init_bcma(); + break; +#endif + } } int nvram_getenv(char *name, char *val, size_t val_len)