/* Probe for NVRAM header */ static int early_nvram_init(void) { struct nvram_header *header; int i; u32 *src, *dst; #ifdef CONFIG_MTD_NFLASH hndnand_t *nfl_info = NULL; uint32 blocksize; #endif char *nvram_space_str; int bootdev; uint32 flash_base; uint32 lim = SI_FLASH_WINDOW; uint32 off; hndsflash_t *sfl_info; header = (struct nvram_header *)ram_nvram_buf; if (header->magic == NVRAM_MAGIC) { if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) { nvram_inram = TRUE; goto found; } } bootdev = soc_boot_dev((void *)sih); #ifdef CONFIG_MTD_NFLASH if (bootdev == SOC_BOOTDEV_NANDFLASH) { if ((nfl_info = hndnand_init(sih)) == NULL) return -1; flash_base = nfl_info->base; blocksize = nfl_info->blocksize; off = blocksize; for (; off < NFL_BOOT_SIZE; off += blocksize) { if (hndnand_checkbadb(nfl_info, off) != 0) continue; header = (struct nvram_header *)(flash_base + off); if (header->magic != NVRAM_MAGIC) continue; /* Read into the nand_nvram */ if ((header = nand_find_nvram(nfl_info, off)) == NULL) continue; if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) goto found; } } else #endif if (bootdev == SOC_BOOTDEV_SFLASH || bootdev == SOC_BOOTDEV_ROM) { /* Boot from SFLASH or ROM */ if ((sfl_info = hndsflash_init(sih)) == NULL) return -1; lim = sfl_info->size; BUG_ON(request_resource(&iomem_resource, &norflash_region)); flash_base = sfl_info->base; BUG_ON(IS_ERR_OR_NULL((void *)flash_base)); off = FLASH_MIN; while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *)(flash_base + off - nvram_space); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) { goto found; } off += DEF_NVRAM_SPACE; } } else { /* This is the case bootdev == SOC_BOOTDEV_PFLASH, not applied on NorthStar */ ASSERT(0); } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ header = (struct nvram_header *)(flash_base + 4 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) { goto found; } header = (struct nvram_header *)(flash_base + 1 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) { goto found; } return -1; 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 < MAX_NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); nvram_space_str = early_nvram_get("nvram_space"); if (nvram_space_str) nvram_space = bcm_strtoul(nvram_space_str, NULL, 0); return 0; }
/* Probe for NVRAM header */ static int early_nvram_init(void) { struct nvram_header *header; chipcregs_t *cc; int i; uint32 base, off, lim; u32 *src, *dst; uint32 fltype; char *nvram_space_str; #ifdef NFLASH_SUPPORT hndnand_t *nfl_info = NULL; uint32 blocksize; #endif hndsflash_t *sfl_info = NULL; header = (struct nvram_header *)ram_nvram_buf; if (header->magic == NVRAM_MAGIC) { if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { nvram_inram = TRUE; goto found; } } if ((cc = si_setcore(sih, CC_CORE_ID, 0)) != NULL) { #ifdef NFLASH_SUPPORT if ((sih->ccrev == 38) && ((sih->chipst & (1 << 4)) != 0)) { fltype = NFLASH; base = KSEG1ADDR(SI_FLASH1); } else #endif { fltype = readl(&cc->capabilities) & CC_CAP_FLASH_MASK; base = KSEG1ADDR(SI_FLASH2); } switch (fltype) { case PFLASH: lim = SI_FLASH2_SZ; break; case SFLASH_ST: case SFLASH_AT: if ((sfl_info = hndsflash_init(sih)) == NULL) return -1; lim = sfl_info->size; break; #ifdef NFLASH_SUPPORT case NFLASH: if ((nfl_info = hndnand_init(sih)) == NULL) return -1; lim = SI_FLASH1_SZ; break; #endif case FLASH_NONE: default: return -1; } } else { /* extif assumed, Stop at 4 MB */ base = KSEG1ADDR(SI_FLASH1); lim = SI_FLASH1_SZ; } #ifdef NFLASH_SUPPORT if (nfl_info != NULL) { blocksize = nfl_info->blocksize; off = blocksize; for (; off < NFL_BOOT_SIZE; off += blocksize) { if (hndnand_checkbadb(nfl_info, off) != 0) continue; header = (struct nvram_header *) KSEG1ADDR(base + off); if (header->magic != NVRAM_MAGIC) continue; /* Read into the nand_nvram */ if ((header = nand_find_nvram(nfl_info, off)) == NULL) continue; if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) goto found; } } else #endif /* NFLASH_SUPPORT */ { off = FLASH_MIN; #ifdef RTN66U_NVRAM_64K_SUPPORT header = (struct nvram_header *) KSEG1ADDR(base + lim - 0x8000); if(header->magic==0xffffffff) { header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { nvram_32_reset=1; goto found; } } #endif while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *) KSEG1ADDR(base + off - MAX_NVRAM_SPACE); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } off += DEF_NVRAM_SPACE; } } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } return -1; 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 < MAX_NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); nvram_space_str = early_nvram_get("nvram_space"); if (nvram_space_str) nvram_space = bcm_strtoul(nvram_space_str, NULL, 0); return 0; }
static struct nvram_header * BCMINITFN(find_nvram)(si_t *sih, bool embonly, bool *isemb) { struct nvram_header *nvh; uint32 off, lim = SI_FLASH2_SZ; uint32 flbase = SI_FLASH2; int bootdev; #ifdef NFLASH_SUPPORT hndnand_t *nfl_info = NULL; #endif #ifdef _CFE_ hndsflash_t *sfl_info = NULL; #endif bootdev = soc_boot_dev((void *)sih); #ifdef NFLASH_SUPPORT if (bootdev == SOC_BOOTDEV_NANDFLASH) { /* Init nand anyway */ nfl_info = hndnand_init(sih); if (nfl_info) flbase = nfl_info->phybase; } else #endif /* NFLASH_SUPPORT */ if (bootdev == SOC_BOOTDEV_SFLASH) { #ifdef _CFE_ /* Init nand anyway */ sfl_info = hndsflash_init(sih); if (sfl_info) { flbase = sfl_info->phybase; lim = sfl_info->size; } #else if (sih->ccrev == 42) flbase = SI_NS_NORFLASH; #endif } if (!embonly) { *isemb = FALSE; #ifdef NFLASH_SUPPORT if (nfl_info) { uint32 blocksize; blocksize = nfl_info->blocksize; off = blocksize; for (; off < nfl_boot_size(nfl_info); off += blocksize) { if (hndnand_checkbadb(nfl_info, off) != 0) continue; nvh = (struct nvram_header *)OSL_UNCACHED(flbase + off); if (nvh->magic != NVRAM_MAGIC) continue; /* Read into the nand_nvram */ if ((nvh = nand_find_nvram(nfl_info, off)) == NULL) continue; if (nvram_calc_crc(nvh) == (uint8)nvh->crc_ver_init) return nvh; } } else #endif /* NFLASH_SUPPORT */ { off = FLASH_MIN; while (off <= lim) { nvh = (struct nvram_header *) OSL_UNCACHED(flbase + off - MAX_NVRAM_SPACE); if (nvh->magic == NVRAM_MAGIC) { if (nvram_calc_crc(nvh) == (uint8) nvh->crc_ver_init) { return (nvh); } } off <<= 1; } } #ifdef BCMDBG printf("find_nvram: nvram not found, trying embedded nvram next\n"); #endif /* BCMDBG */ } /* * Provide feedback to user when nvram corruption detected. * Must be non-BCMDBG for customer release. */ printf("Corrupt NVRAM found, trying embedded NVRAM next.\n"); /* Now check embedded nvram */ *isemb = TRUE; nvh = (struct nvram_header *)OSL_UNCACHED(flbase + (4 * 1024)); if (nvh->magic == NVRAM_MAGIC) return (nvh); nvh = (struct nvram_header *)OSL_UNCACHED(flbase + 1024); if (nvh->magic == NVRAM_MAGIC) return (nvh); #ifdef _CFE_ nvh = (struct nvram_header *)embedded_nvram; if (nvh->magic == NVRAM_MAGIC) return (nvh); #endif printf("find_nvram: no nvram found\n"); return (NULL); }