/* Probe for NVRAM header */ static int early_nvram_init(void) { struct nvram_header *header; chipcregs_t *cc; struct sflash *info = NULL; int i; uint32 base, off, lim; u32 *src, *dst; uint32 fltype; #ifdef NFLASH_SUPPORT struct nflash *nfl_info = NULL; uint32 blocksize; #endif header = (struct nvram_header *)ram_nvram_buf; 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 ((info = sflash_init(sih, cc)) == NULL) return -1; lim = info->size; break; #ifdef NFLASH_SUPPORT case NFLASH: if ((nfl_info = nflash_init(sih, cc)) == 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; while (off <= lim) { if (nflash_checkbadb(sih, cc, off) != 0) { off += blocksize; continue; } header = (struct nvram_header *) KSEG1ADDR(base + off); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } off += blocksize; } } else #endif 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_valid(header)) goto found; } #endif while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); if (nvram_valid(header)) goto found; off <<= 1; } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); if (nvram_valid(header)) goto found; header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (nvram_valid(header)) 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 < NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); return 0; }
/* Read the flash ID and set the globals */ int sysFlashInit(char *flash_str) { osl_t *osh; uint32 fltype = PFLASH; uint16 flash_vendid = 0; uint16 flash_devid = 0; int idx; struct sflash *sflash; /* * Check for serial flash. */ sih = si_kattach(SI_OSH); ASSERT(sih); osh = si_osh(sih); cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); ASSERT(cc); flashutl_base = (void *)OSL_UNCACHED((uintptr)SI_FLASH2); /* Select SFLASH ? */ fltype = R_REG(osh, &cc->capabilities) & CC_CAP_FLASH_MASK; if (fltype == SFLASH_ST || fltype == SFLASH_AT) { if (sih->ccrev == 12) flashutl_base = (void *)OSL_UNCACHED((uintptr)SI_FLASH2); else flashutl_base = (void *)OSL_CACHED((uintptr)SI_FLASH2); sflash = sflash_init(sih, cc); flashutl_cmd = &sflash_cmd_t; flashutl_desc = &sflash_desc; flashutl_desc->size = sflash->size; if (flash_str) sprintf(flash_str, "SFLASH %d kB", sflash->size/1024); return (0); } flashutl_wsz = (R_REG(osh, &cc->flash_config) & CC_CFG_DS) ? sizeof(uint16) : sizeof(uint8); ASSERT(flashutl_wsz == sizeof(uint8) || flashutl_wsz == sizeof(uint16)); /* * Parallel flash support * Some flashes have different unlock addresses, try each it turn */ for (idx = 0; fltype == PFLASH && idx < ARRAYSIZE(flash_cmds); idx ++) { flashutl_cmd = &flash_cmds[idx]; if (flashutl_cmd->type == OLD) continue; if (flashutl_cmd->read_id) { cmd(flashutl_cmd->read_id, CMD_ADDR); /* Delay for turn around time */ OSL_DELAY(1); } #ifdef MIPSEB #ifdef BCMHND74K flash_vendid = flash_readword(FLASH_ADDR(0)^6); flash_devid = flash_readword(FLASH_ADDR(2)^6); #else /* !74K, bcm33xx */ flash_vendid = flash_readword(FLASH_ADDR(2)); flash_devid = flash_readword(FLASH_ADDR(0)); #endif /* BCMHND74K */ #else flash_vendid = flash_readword(FLASH_ADDR(0)); flash_devid = flash_readword(FLASH_ADDR(2)); #endif /* MIPSEB */ /* Funky AMD, uses 3 byte device ID so use first byte (4th addr) to * identify it is a 3-byte ID and use the next two bytes (5th & 6th addr) * to form a word for unique identification of format xxyy, where * xx = 5th addr and yy = 6th addr */ if ((flash_vendid == 1) && ((flash_devid == 0x227e && flashutl_wsz == sizeof(uint16)) || (flash_devid == 0x7e && flashutl_wsz == sizeof(uint8)))) { /* Get real devid */ uint16 flash_devid_5th; #ifdef MIPSEB #ifdef BCMHND74K flash_devid_5th = flash_readword(FLASH_ADDR(0x1c)^6) << 8; flash_devid = (flash_readword(FLASH_ADDR(0x1e)^6) & 0xff) | flash_devid_5th; #else /* !74K, bcm33xx */ flash_devid_5th = flash_readword(FLASH_ADDR(0x1e)) << 8; flash_devid = (flash_readword(FLASH_ADDR(0x1c)) & 0xff) | flash_devid_5th; #endif /* BCMHND74K */ #else flash_devid_5th = flash_readword(FLASH_ADDR(0x1c)) << 8; flash_devid = (flash_readword(FLASH_ADDR(0x1e)) & 0xff) | flash_devid_5th; #endif /* MIPSEB */ } flashutl_desc = flashes; while (flashutl_desc->mfgid != 0 && !(flashutl_desc->mfgid == flash_vendid && flashutl_desc->devid == flash_devid)) { flashutl_desc++; } if (flashutl_desc->mfgid != 0) break; } if (flashutl_desc->mfgid == 0) { flashutl_desc = NULL; flashutl_cmd = NULL; } else { flashutl_cmd = flash_cmds; while (flashutl_cmd->type != 0 && flashutl_cmd->type != flashutl_desc->type) flashutl_cmd++; if (flashutl_cmd->type == 0) flashutl_cmd = NULL; } if (flashutl_cmd != NULL) { flash_reset(); } if (flashutl_desc == NULL) { if (flash_str) sprintf(flash_str, "UNKNOWN 0x%x 0x%x", flash_vendid, flash_devid); DPRINT(("Flash type UNKNOWN\n")); return 1; } if (flash_str) strcpy(flash_str, flashutl_desc->desc); DPRINT(("Flash type \"%s\"\n", flashutl_desc->desc)); return 0; }
/* Probe for NVRAM header */ static void __init early_nvram_init(void) { 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) & CAP_FLASH_MASK) { case PFLASH: lim = SB_FLASH2_SZ; break; case SFLASH_ST: case SFLASH_AT: if ((info = sflash_init(cc)) == NULL) return; lim = info->size; break; case FLASH_NONE: default: return; } } else { /* extif assumed, Stop at 4 MB */ base = KSEG1ADDR(SB_FLASH1); lim = SB_FLASH1_SZ; } /* 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"); for (i = 0; i < 0x1ff0; i++) { if (*src == 0xFFFFFFFF) break; *dst++ = *src++; } return; } 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; } /* 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) goto found; header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); 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++); }
int flashDrvLibInit(void) { FLASH_TYPES dev; FLASH_VENDORS vendor; int i; uint32 fltype = PFLASH; osl_t *osh; struct sflash *sflash; if (flashDrvInitialized) return (OK); flashBaseAddress = FLASH_BASE_ADDRESS_ALIAS; /* * Check for serial flash. */ sih = si_kattach(SI_OSH); ASSERT(sih); osh = si_osh(sih); cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); ASSERT(cc); /* Select SFLASH */ fltype = R_REG(osh, &cc->capabilities) & CC_CAP_FLASH_MASK; if (fltype == SFLASH_ST || fltype == SFLASH_AT) { sflash = sflash_init(sih, cc); if (sflash == NULL) { printf("flashInit(): Unrecognized Device (SFLASH)\n"); return (ERROR); } flashDrvFuncs = &flashsflash; flashDrvFuncs->flashAutoSelect(&dev, &vendor); flashSectorCount = sflash->numblocks; flashDevSectorSize = sflash->blocksize; if (flashVerbose) { printf("flashInit(): SFLASH Found\n"); } } else { flashDrvFuncs = &flashs29gl256p; flashDrvFuncs->flashAutoSelect(&dev, &vendor); if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash29gl128; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash29l640; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash29l320; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash29l160; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash28f320; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } switch (vendor) { case AMD: case ALLIANCE: case MXIC: switch (dev) { case FLASH_2F040: flashSectorCount = 8; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 2F040 Found\n"); break; case FLASH_2F080: flashSectorCount = 16; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 2F080 Found\n"); break; case FLASH_2L081: flashSectorCount = 16; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 29LV081B Found\n"); break; case FLASH_2L160: case FLASH_2L017: flashSectorCount = 32; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 29LV160D Found\n"); break; case FLASH_2L640: case FLASH_MX2L640: flashSectorCount = 128; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 29LV640M Found\n"); break; case FLASH_29GL128: /* Spansion 29GL128 is physically 128 sector count * To make flash support backward compatible to old device, * only use 64 for 8MB */ flashSectorCount = 64; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): 29GL128 Found\n"); break; case FLASH_2L320: flashSectorCount = 64; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 29LV320D Found\n"); break; case FLASH_S29GL128P: flashSectorCount = 128; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): FLASH_S29GL128P Found\n"); break; case FLASH_S29GL256P: flashSectorCount = 256; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): S29GL256P Found\n"); break; case FLASH_S29GL512P: flashSectorCount = 512; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): FLASH_S29GL512P Found\n"); break; case FLASH_S29GL01GP: flashSectorCount = 1024; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): FLASH_S29GL01GP Found\n"); break; default: printf("flashInit(): Unrecognized Device (0x%02X)\n", dev); return (ERROR); } break; case INTEL: switch (dev) { case FLASH_2F320: flashSectorCount = 32; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): 28F320 Found\n"); break; default: printf("flashInit(): Unrecognized Device (0x%02X)\n", dev); return (ERROR); } break; default: printf("flashInit(): Unrecognized Vendor (0x%02X)\n", vendor); return (ERROR); } } flashSize = flashDevSectorSize * flashSectorCount; for (i = 0; i < TOTAL_LOADED_SECS; i++) { flashLoadedSectors[i].buffer = malloc(FLASH_SECTOR_SIZE); if (flashLoadedSectors[i].buffer == NULL) { printf("flashInit(): malloc() failed\n"); for (; i > 0; i--) { free(flashLoadedSectors[i-1].buffer); } return (ERROR); } flashLoadedSectors[i].sector = -1; flashLoadedSectors[i].dirty = 0; flashLoadedSectors[i].fsSemID = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE); } flashDrvInitialized ++; return (OK); }
mod_init_t sflash_mtd_init(void) { struct pci_dev *pdev; int ret = 0; struct sflash *info; uint i; #ifdef CONFIG_MTD_PARTITIONS struct mtd_partition *parts; #endif if (!(pdev = pci_find_device(VENDOR_BROADCOM, SB_CC, NULL))) { printk(KERN_ERR "sflash: chipcommon not found\n"); return -ENODEV; } memset(&sflash, 0, sizeof(struct sflash_mtd)); init_MUTEX(&sflash.lock); /* attach to the backplane */ if (!(sflash.sbh = sb_kattach(SB_OSH))) { printk(KERN_ERR "sflash: error attaching to backplane\n"); ret = -EIO; goto fail; } /* Map registers and flash base */ if (!(sflash.cc = ioremap_nocache(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)))) { printk(KERN_ERR "sflash: error mapping registers\n"); ret = -EIO; goto fail; } /* Initialize serial flash access */ if (!(info = sflash_init(sflash.sbh, sflash.cc))) { printk(KERN_ERR "sflash: found no supported devices\n"); ret = -ENODEV; goto fail; } printk(KERN_INFO "sflash: found serial flash; blocksize=%dKB, numblocks=%d, size=%dKB\n",info->blocksize/1024,info->numblocks,info->size/1024); /* Setup region info */ sflash.region.offset = 0; sflash.region.erasesize = info->blocksize; sflash.region.numblocks = info->numblocks; if (sflash.region.erasesize > sflash.mtd.erasesize) sflash.mtd.erasesize = sflash.region.erasesize; sflash.mtd.size = info->size; sflash.mtd.numeraseregions = 1; /* Register with MTD */ sflash.mtd.name = "sflash"; sflash.mtd.type = MTD_NORFLASH; sflash.mtd.flags = MTD_CAP_NORFLASH; sflash.mtd.eraseregions = &sflash.region; sflash.mtd.module = THIS_MODULE; sflash.mtd.erase = sflash_mtd_erase; sflash.mtd.read = sflash_mtd_read; sflash.mtd.write = sflash_mtd_write; sflash.mtd.priv = &sflash; #ifdef CONFIG_MTD_PARTITIONS parts = init_mtd_partitions(&sflash.mtd, sflash.mtd.size); for (i = 0; parts[i].name; i++); ret = add_mtd_partitions(&sflash.mtd, parts, i); #else ret = add_mtd_device(&sflash.mtd); #endif if (ret) { printk(KERN_ERR "sflash: add_mtd failed\n"); goto fail; } return 0; fail: if (sflash.cc) iounmap((void *) sflash.cc); if (sflash.sbh) sb_detach(sflash.sbh); return ret; }
/* Read the flash ID and set the globals */ int sysFlashInit(char *flash_str) { uint32 fltype = PFLASH; uint16 flash_vendid = 0; uint16 flash_devid = 0; uint16* flash = (uint16*)0xbfc00000; int idx; struct sflash *sflash; void *sbh; /* * Check for serial flash. */ sbh = sb_kattach(); ASSERT(sbh); cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); if (cc) { flash = (uint16*)0xbc000000; fltype = R_REG(&cc->capabilities) & CAP_FLASH_MASK; /* Select SFLASH ? */ if (fltype == SFLASH_ST || fltype == SFLASH_AT) { sflash = sflash_init(cc); flashutl_cmd = &sflash_cmd_t; flashutl_desc = &sflash_desc; flashutl_desc->size = sflash->size; if (flash_str) sprintf(flash_str, "SFLASH %d kB", sflash->size/1024); return(0); } } flashutl_base = (uint8*)flash; /* * Parallel flash support * Some flashes have different unlock addresses, try each it turn */ idx = sizeof(flash_cmds)/sizeof(flash_cmds_t) - 2; flashutl_cmd = &flash_cmds[idx--]; while((fltype == PFLASH) && flashutl_cmd->type) { if (flashutl_cmd->read_id) cmd(flashutl_cmd->read_id, CMD_ADDR); #ifdef MIPSEB flash_vendid = *(flash + 1); flash_devid = *flash; #else flash_vendid = *flash; flash_devid = *(flash + 1); #endif /* Funky AMD */ if ((flash_vendid == 1) && (flash_devid == 0x227e)) { /* Get real devid */ #ifdef MIPSEB flash_devid = *(flash+0xe); #else flash_devid = *(flash+0xf); #endif } flashutl_desc = flashes; while (flashutl_desc->mfgid != 0 && !(flashutl_desc->mfgid == flash_vendid && flashutl_desc->devid == flash_devid)) { flashutl_desc++; } if (flashutl_desc->mfgid != 0) break; flashutl_cmd = &flash_cmds[idx--]; } if (flashutl_desc->mfgid == 0) { flashutl_desc = NULL; flashutl_cmd = NULL; } else { flashutl_cmd = flash_cmds; while (flashutl_cmd->type != 0 && flashutl_cmd->type != flashutl_desc->type) flashutl_cmd++; if (flashutl_cmd->type == 0) flashutl_cmd = NULL; } if (flashutl_cmd != NULL) { flash_reset(); } if (flashutl_desc == NULL) { if (flash_str) sprintf(flash_str, "UNKNOWN 0x%x 0x%x", flash_vendid, flash_devid); DPRINT(("Flash type UNKNOWN\n")); return 1; } if (flash_str) strcpy(flash_str, flashutl_desc->desc); DPRINT(("Flash type \"%s\"\n", flashutl_desc->desc)); return 0; }
/* Probe for NVRAM header */ static int early_nvram_init(void) { struct nvram_header *header; chipcregs_t *cc; struct sflash *info = NULL; int i; uint32 base, off, lim; u32 *src, *dst; if ((cc = si_setcore(sih, CC_CORE_ID, 0)) != NULL) { base = KSEG1ADDR(SI_FLASH2); switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) { case PFLASH: lim = SI_FLASH2_SZ; break; case SFLASH_ST: case SFLASH_AT: if ((info = sflash_init(sih, cc)) == NULL) return -1; lim = info->size; break; case FLASH_NONE: default: return -1; } } else { /* extif assumed, Stop at 4 MB */ base = KSEG1ADDR(SI_FLASH1); lim = SI_FLASH1_SZ; } off = FLASH_MIN; while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } off <<= 1; } /* 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 < NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); return 0; }